IE9以降のブラウザとNede.jsで動きます。
AMDでも動くはずです。
試していません。動かなかったら教えてください。
どんなライブラリか?
こんな感じ
dateAdder(new Date(2014,10,27), {days: 1})
dateAdder(new Date(2014,10,27), {hours: 1})
dateAdder(new Date(2014,10,27), {days: 1, hours: 1})
JavaScriptのDateオブジェクトに足し算したり引き算したりする関数です。
なぜ作ったか?
ledsun/generate-google-calendar-url · GitHubを使ってGoogleカレンダー用のURLを作る時に使おうと思いました。
予定に開始時刻だけあって終了時刻が無かったら、終了時刻を開始時刻の1時間後に設定します。
どうすればJavaScriptで一時間後の時刻が得られるでしょうか?
一般にJavaScriptで時間を足す処理を書くとこうです。
var newEnd = new Date(date.getTime())
newEnd.setHours(date.getHours() + value)
二行必要なのが、ちょっと嫌いです。
StackOverflowで検索しても似た感じです。
var today = new Date();
var tomorrow = new Date(today);
tomorrow.setDate(today.getDate()+1);
npmパッケージ
111247パッケージを誇るnpmを検索してみます。
parseメソッドやformatメソッドはちょっと余計です。
addメソッドの実装
は参考になりそうです。
1つのメソッドでget/setを両方やるjQueryぽいインターフェースは頂けません。
他のインターフェースと混ぜると辛いです。
実装やテストもコストが高いです。
Math Functionsに加算があります。新しいオブジェクトを返す、非破壊的なメソッドなのも良いです。
ただ、
- 加算と減産を分ける価値が分かりません
- 比較メソッドの価値も分かりません。getTimeすれば良くないです?
- min/maxはreduceで十分な気もします
- サポートしている単位が多いのも気になります。decadeって使います?10年足せば良くないですか?
名前がかっこいいです。
でも欲しいのはDateオブジェクトの代替えではありません。
そんな訳で、手頃なものが無いので作りました。
作っていた時の四方山話
Dateの標準API
主にゲッターセッター。
妙に統一感がありません。
特に年月日
- getFullYear
- getDate
- getMonth
時以下は単位複数形で統一されて居るのに
英語的には正しいのかもしれませんね・・・。
日付のテストコードの話
https://twitter.com/ledsun/status/538131617382817792
変更した日付の値が期待通りかassertで比べたいです。
ところがassert.equalもstrictEqualも時刻の比較はしてくれない。
オブジェクトが同一かどうかを比較します。
結論からいうと頭に+を付けて数値に変換して比較しました。
オレオレassertはダメ
こんなの
var assertDate = function(expct, actual, message){
assert.equal(expect.getTime(), actual.getTime(), message)
}
原則的にオレオレassertは悪手です。
- オレオレassertの動作を理解しなくてはいけません
- 関連のあるテストコード以外のコードも読まなくてはいけません
テストコードは定石がすくないので、
他人が書いたテストコードはメンテナンスしづらいです。
テストコードを書くコストが減っても、読むコストが増えると状況は悪化します。
getTime
最少単位で比較すれば良いのでミリ秒に変換して比較します。
assert.equal(expect.getTime(), actual.getTime())
毎回getTimeを書くのは面倒です。
Date系ライブラリのテストコードを見てみましょう。
valueOf派
https://github.com/JerrySievert/date-utils/blob/master/test/date-new-test.js#L11
assert.equal(expect.valueOf(), actual.valueOf())
プリミティブ値の比較は仕様上好ましそうです。
getTimeとメソッド名の長さも得られる値も同じです。
数値にキャスト派
https://github.com/jquense/date-math/blob/master/test.js#L27
https://github.com/timruffles/immutable-date/blob/master/test.js#L11
assert.equal(+expect, +actual)
JavaScriptの標準から外れずに、最も短く書けるのでこの記法にしました。
開発環境を自慢
ソースコードはES5対応です。
実際に各ブラウザで動くかはsaucelabsで確認しました。
mochaで書いたテストコードをzuulでブラウザで動かしました。
最初はもっとたくさんのブラウザでテストしました。
時間掛かかりました。
各ブラウザの動作可能な最も古いバージョンだけテストすることにしました。
1セット約2分掛かかります。
こんなバッジがもらえます。
最初はtestling使う予定でした。
ローカルでテストして、travis.ci設定して、githubにpushしても反応がありません。
調べてみたら
ci.testling.com Service Timeout · Issue #88 · substack/testling · GitHub
でした。
generate-google-calendar-url
もブラウザとNode.jsで動きます。
EventEmitter2を真似て手で書きました。
UMD.jsという標準を知り、
従うことにしました。
ソフトウェア開発のコツは「解決したい問題以外は他人に押し付ける」です。
手で書いたら、ソースコードが読みにくくなったのでgulp-umdを使いました。
元が1ファイルだったので楽でした。
複数ファイルに分けるとどうなるんでしょうね?
Jxck_さんの教え
npm で依存もタスクも一元化する - Qiita
"script" を "npm run" で実行する場合は、パスが自動で通る
必要なコマンドはすべてnpmから実行出来るようにしました。
- npm run build
- npm test
- npm run browser
- npm run saucelabs
npm run saucelabs
はtravis.ci用なので人間はあまり実行しないはずです。
t-wadaさんの教え
細かすぎて伝わらない package.json 小ネタ三選 - t-wadaのブログ
- package.json の files フィールド
- package.json のフィールド並び順に悩むくらいなら fixpack
- ライセンス、 MIT で良いなら mit-license.org
一通りやりました。
もちろんpower-assert使いました。
途中でテストコマンド間違えてエラー詳細で無くなったらパニックに陥りました。
知らず知らずのうちに頼り切りです。
まとめ
npmモジュールの開発は簡単ですね<3
ソースコードは40行しかないのに、こんなに書くことがある!