🕊️

DenoのDateTimeライブラリPteraをリリースしました

5 min read

Ptera

ptera-logo

DenoのDateTimeライブラリであるPteraをリリースしたので、その紹介(宣伝)をします。
素敵なロゴはDenoのイラストを数多く書いてらっしゃる hashrockさんにデザインしていただきました!

これまでNode.jsのライブラリはMoment.jsDay.jsLuxondate-fns
などいくつか選択肢がありました。
ただ、Denoで書かれているThird Partyライブラリは自分が調査した限り見当たらなかったので、作ってみました。

Getting Started

メインで使用するAPIはdatetimeです。

引数なしの場合、ローカルの現在時刻で返します。ISO8601の文字列やJavaScriptのDateなども引数としてサポートしています。

import { datetime } from "https://deno.land/x/ptera/mod.ts";

// now in local time
datetime();

// parse ISO 8601
datetime("2021-06-30T21:15:30.200");

// JavaScript Date
datetime(new Date());

他にもTimezoneやIntl、日付の差分、Parse, Format, 基本的なUtilitiesを提供しています。

実際に使用する際はドキュメントを参照してください。

これまでのライブラリとの比較

これまでのDateTimeライブラリを分類してみると大きく2つに分類できます。

  • JavaScriptのDateクラスをラップするクラスを提供するライブラリ: Moment.js, Day.js, Luxon
  • JavaScriptのDateクラスに対するUtilitiesを提供するライブラリ: date-fns

JavaScriptのDateの仕様にはハマりやすい部分があり、個人的にそのまま使用するのは避けたいと思っています。
(月が0から始まったり、getDayが曜日を返すなど)

なので、PteraはMoment.jsやDay.js、Luxonのように独自のラッパークラスを定義しています。

また、deno_stdにもdatetimeのパッケージがあり、Dateクラスのhelperメソッドが提供されています。

Dateクラス関連の処理は標準ライブラリに任せたほうがいいと判断したのも理由の1つです。

Luxon, Day.jsとの比較

Luxon, Day.jsとPteraを比較してみます。

Moment.jsはdeprecatedになったので割愛します。

Immutable

Luxon, Day.jsと同じく、イミュータブルな設計にしています。

toUTCtoZonedTimeなどの日付を変換するAPIがありますが、インスタンスの属性を変えるのではなく、常に新しいインスタンスを返します。

const dt = datetime();
const newInstance = dt.toUTC();

Parse, Format

Day.jsと同じく、Pteraのdatetimeは任意の型を引数に渡すことができます。

// parse ISO 8601
datetime("2021-06-30T21:15:30.200");

// JavaScript Date
datetime(new Date());

// Object
datetime({ year: 2021, month: 3, day: 21 });

// Unixtime
datetime(1625238137000);

// Array
datetime([2021, 6, 11, 13, 30, 30]);

Luxonは引数の種類によって、メソッドも異なります。(fromISO, fromObjectなど)

https://moment.github.io/luxon/#/why

Luxon forces you to decide that you want to call fromISO or whatever. The
upshot of all that is that Luxon feels like a different library; that's why
it's not Moment 3.0.

またDay.js, Luxonと同じく、ISO 8601だけではなく、任意のフォーマットでパースしたり、フォーマットして文字列にできます。
標準のIntl APIを使用しており、任意のLocaleでもパース、フォーマットできます。

Ptera parse

Ptera format

const parsedDate = datetime().parse(
  "5/Aug/2021:14:15:30 +0900",
  "d/MMM/YYYY:HH:mm:ss ZZ",
);
// support locale
datetime().parse("2021 лютий 03", "YYYY MMMM dd", { locale: "uk" });

// format to ISO 8601
const dt = datetime({
  year: 2021,
  month: 7,
  day: 21,
  hour: 23,
  minute: 30,
  second: 59,
});
dt.toISO(); // 2021-07-21T23:30:59.000Z
dt.toISODate(); // 2021-07-21
dt.toISOWeekDateDate(); // 2021-W29-3
dt.toISOTime(); // 23:30:59.000
dt.format("YYYY/MMMM/dd"); // 2021/July/21
dt.setLocale("fr").format("YYYY/MMMM/dd"); // // 2021/juillet/21

Day.jsはJavaScriptのDateと同じく、月は0から始まります。(1月の場合は0)
Luxonは月の数字と同じです。

PteraはLuxonと同じく月の数字と同じ値にしています。

const luxon = DateTime.fromISO("2021-07-21T23:00:59.100");
const dayjsDate = dayjs("2021-07-21T23:00:59.100");
const ptera = datetime("2021-07-21T23:00:59.100");
dayjsDate.month(); // 6
luxon.month; // 7
ptera.month; // 7

曜日

Dayjsはlocaleの設定によってweekdayが変わります。 https://day.js.org/docs/en/get-set/weekday
Luxonは月曜が1、日曜が7です。
JavaScriptのDateは日曜が0、土曜が6となっています。

PteraはDateの仕様と同じく、日曜を0, 土曜を6としています。

datetime("2021-07-11").weekDay(); // 0
datetime("2021-07-17").weekDay(); // 6

Timezone

DayjsはpluginをimportしてTimezoneを扱います。

import dayjs from "dayjs";
import timezone from "dayjs/plugin/timezone";
dayjs.extend(timezone);

dayjs.tz("2021-06-01 12:00", "America/New_York");

LuxonはsetZone()を使用します。

const luxon = DateTime.fromISO("2021-07-21T23:00:59.100");
luxon.setZone("America/New_York");

pteraはLuxonと同じくpluginをimportすることなく、toZonedTimeで任意のTimezoneの時刻に変換できます。

const local = datetime("2021-07-21T23:00:59.100");
// DateTime {
//   year: 2021,
//   month: 7,
//   day: 21,
//   hour: 23,
//   minute: 0,
//   second: 59,
//   millisecond: 100,
//   timezone: "Asia/Tokyo",
//   valid: true,
//   locale: "en"
// }

const NewYork = local.toZonedTime("America/New_York");
// DateTime {
//   year: 2021,
//   month: 7,
//   day: 21,
//   hour: 10,
//   minute: 0,
//   second: 59,
//   millisecond: 100,
//   timezone: "America/New_York",
//   valid: true,
//   locale: "en"
// }

今後について

不足している機能の追加は今後行っていきます。(DSTやDurationなど)
また、今後はTemporalもDenoで使用可能になるでしょう。
TemporalがあればDateクラスのラッパークラスは必要なくなると思うので、PteraはTemporalに対するutilitiesを提供するライブラリにできるといいのかなとぼんやり考えています。
その場合、APIはかなり変わると思いますが...

最後に

Denoの日付ライブラリPteraの紹介でした。

不明点、バグなどあればissue、PRお待ちしています。

starももらえるとめちゃくちゃ喜びます。