2016-06-17 TimeKeeper.js (bouzuya/time-keeper-js) をつくった
TimeKeeper.js (bouzuya/time-keeper-js) をつくった。
TimeKeeper.js は simple な date-time library 。
次の特徴を持つ。
- simple な api
- milliseconds に対応しない
- day of week に対応しない
- ISO8601 の標準の形式 (
2006-01-02T15:04:05-07:00
) 以外の formatter に対応しない - invalid な状態 (NullObject) に対応しない
- mutable な状態に対応しない
- TypeScript (
.d.ts
) に対応する
極力 simple な api にしている。README の Example ですべての api だ。
import * as assert from 'assert';
import { now, parseISOString, parseUNIXTime } from 'time-keeper';
const dt1 = now();
const dt2 = parseUNIXTime(dt1.toUNIXTime());
assert(dt1.toString() === dt2.toString());
const dt3 = parseISOString('2016-06-17T23:28:40+09:00');
assert(dt3.get('year') === 2016);
assert(dt3.get('month') === 6);
assert(dt3.get('date') === 17);
assert(dt3.get('hour') === 23);
assert(dt3.get('minute') === 28);
assert(dt3.get('second') === 40);
assert(dt3.toTimeZoneOffsetString() === '+09:00');
const dt4 = dt3.inTimeZone('+00:00');
assert(dt3.toISOString() === '2016-06-17T23:28:40+09:00');
assert(dt4.toISOString() === '2016-06-17T14:28:40+00:00');
const dt5 = dt4.plus(2, 'day');
assert(dt4.toISOString() === '2016-06-17T14:28:40+00:00');
assert(dt5.toISOString() === '2016-06-19T14:28:40+09:00');
目的。
TimeKeeper.js の目的としては次の 2 つだ。
- momentjs/moment の誤用の防止
- bouzuya/beater 0.4.0 の検証
JavaScript 界隈では定番の date-time library である moment
。moment
はとても良く出来た library だ。しかし moment
はいくつかの罠があり、ぼくのまわりでそれに起因する事故が起きている。例を挙げると、 mutable であること・通常の parse だと time-zone が local になる・invalid な状態を許容する・format()
の指定の誤りなどだ。そこで機能を制限し、自分の想像の範囲で安全に動作する library をつくろうと考えた。
2016-06-16 に書いた beater 0.4.0 の検証を兼ねたかった。適度に小さい library が欲しかった。
実装。
TimeKeeper.js の実装は最近のぼくの標準である Node.js + TypeScript (+typings) を使っている。moment
を wrap しただけのお手軽実装だ。先の目的どおりに test は beater (+ beater-cli) + power-assert 。手堅く慣れた tool を使いつつ、beater の検証を図った感じ。
あとは特徴として TypeScript の String Literal Types を使っている点を挙げたい。上記の Example には文字列で field
や unit
を取る点がある。このあたりは moment
の format()
指定のように誤爆すると思われるかもしれないが、実は TypeScript user なら型安全だ。 TypeScript の String Literal Types なので間違えることなく使える。
ほかには、実装の隠蔽および TypeScript の private constructor をつくれない制約を回避するために、 interface
とそれを返す関数を export
している。Java 界隈なら当たり前のように見かけるのだけど TypeScript ではどうなんだろう……。
感想。
beater 0.4.0 の使い勝手は上々。API は変更されているものの 0.3.0 とほとんど差を感じなかった。browser のほうは試せていないし、怪しいけれど……。
TimeKeeper.js については実用の中で洗練していきたい。