ソフトウェア/javascript/japanese-holidays のバックアップの現在との差分(No.3)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[公開メモ]]

* 日本の休日を求めるための javascript ライブラリを npm と github へ公開しました [#y6d9a7a7]

祝日名が取れて、なおかつメンテナンスしやすい形の
ライブラリが見付からなかったので書いてみました。

一応、複数のライブラリと突き合わせて齟齬がないことを確認しましたが、
運用は個々の責任でお願いします。ミスがあれば教えてください。

法律改正などで休日が変更になっても、よほどのことがない限り definition 
のところをいじるだけで対応できるはずです。

もともとこのライブラリは 2013 年に書かれた物です。
2016年から 「山の日」 が新設されましたが、これに対するコードの追加は、

 LANG: javascript
    [ "山の日",                   simpleHoliday( 8, 11), 2016       ],

の一行だけで済みました。

ライセンスは MIT です。
煮るなり焼くなり好きにしてください。

- npm~
https://www.npmjs.com/package/japanese-holidays
- github~
https://github.com/osamutake/japanese-holidays-js

* 使い方 [#jfc77040]

npm を使うなら、

 LANG:console
 $ npm i japanese-holidays
 $ node
 > Holidays = require('japanese-holidays');
 > Holidays.getHolidaysOf(2016);
 [ { month: 1, date: 1, name: '元日' },
   { month: 1, date: 11, name: '成人の日' },
   { month: 2, date: 11, name: '建国記念の日' },
   { month: 3, date: 20, name: '春分の日' },
   { month: 3, date: 21, name: '振替休日' },
   { month: 4, date: 29, name: '昭和の日' },
   { month: 5, date: 3, name: '憲法記念日' },
   { month: 5, date: 4, name: 'みどりの日' },
   { month: 5, date: 5, name: 'こどもの日' },
   { month: 7, date: 18, name: '海の日' },
   { month: 8, date: 11, name: '山の日' },
   { month: 9, date: 19, name: '敬老の日' },
   { month: 9, date: 22, name: '秋分の日' },
   { month: 10, date: 10, name: '体育の日' },
   { month: 11, date: 3, name: '文化の日' },
   { month: 11, date: 23, name: '勤労感謝の日' },
   { month: 12, date: 23, name: '天皇誕生日' } ]
 > Holidays.isHoliday(new Date(2016,3-1,20));
 '春分の日'
 > Holidays.isHoliday(new Date(2016,3-1,21));
 '振替休日'

npm を使わないなら、~
 https://rawgit.com/osamutake/japanese-holidays-js/master/lib/japanese-holidays.js ~
 https://cdn.rawgit.com/osamutake/japanese-holidays-js/v1.0.6/lib/japanese-holidays.js ~
を読み込めば JapaneseHolidays に必要な関数が入ってきます。

 LANG:javascript
 <script src="https://rawgit.com/osamutake/japanese-holidays-js/master/lib/japanese-holidays.js"></script>
 <script src="https://cdn.rawgit.com/osamutake/japanese-holidays-js/v1.0.6/lib/japanese-holidays.js"></script>
 <script>
   alert( JapaneseHolidays.isHoliday(new Date(2016,3-1,20)) );
 </script>

さらにちゃんとした例をこちらに置きました。

  http://jsbin.com/qicazaroxu/edit?js,output
 http://jsbin.com/qicazaroxu/edit?js,output

リンク先では上記ライブラリを使って休日入りのカレンダーを表示しています。

休日の上にマウスカーソルを置くと、休日名がツールチップとして表示されるはずです。~
(下はスクリーンキャプチャーですので表示されている休日名は変化しません)

&ref(calendar.png,nolink);

* タイムゾーンに注意が必要 [#e7bb3da8]
* タイムゾーンについて [#e7bb3da8]

JapaneseHolidays.isHoliday に与える Date 型の値を作成する際には、
タイムゾーンについてよく考える必要があります。
JapaneseHolidays.isHoliday は与えられた「時刻」ではなく「日付」を元に祝日を判定します。 例えばニュージーランドで

 LANG:javascript
 JapaneseHolidays.isHoliday(new Date()); 
 JapaneseHolidays.isHoliday(new Date(2016,3-1,8)); 

例えばこのコードは一見、「今日」が祝日かどうかを判断しているように読めますが、
実際に判断しているのは「今」が祝日かどうか、です。
とすると、ニュージーランド時間の 2016-03-08 00:00:00 が関数に渡されます。 これは日本時間では 2016-03-07 21:00:00 を表しますが、 isHoliday は与えられた日付 3/8 が休日かどうかを判定するということです。

というのも、このコードが例えばアメリカで実行されたとすると、その時点で
アメリカが例えば8日だったとしても、日本はすでに9日かもしれなくて、
isHoliday は実際には今日でなく明日が祝日かどうかを判断してしまうかも
しれないのです。
多くの場合これは利用者の意図するところだと思います。

同様に、ニュージーランドで
万一、与えた「時刻」において日本で休日かどうかを判定する必要があれば、

 LANG:javascript
 JapaneseHolidays.isHoliday(new Date(2016,3,8)); 
 JapaneseHolidays.isHolidayAt(new Date(2016,3-1,8)); 

を実行してしまうと、これはニュージーランド時間で 2016-03-08 00:00:00 
を表しますから、このとき日本では 2016-03-07 21:00:00 でして、
意図せず前日を判定してしまいます。
を呼んでください。例えばニュージーランドでこれを呼べば、3/7 が休日かどうかが判定されます。

ですので、もしあなたが 2016/03/08 が祝日かどうかを判別したければ、
日時を日本のタイムゾーン居合わせて指定しなければなりません。例えば
* 2019年の改元に対応するためアップデート (v1.0.7) [#re56aa85]

 LANG:javascript
 JapaneseHolidays.isHoliday(new Date(Date.UTC(2016,3,8,-9))); 
普段やり慣れないことで手順を思い出す(調べる)のにとても苦労したためメモしておく。

のように書けばいいわけです。ちょっと分かりづらかったら試してみれば、
+ GitHub でプルリクエストをマージした
+ ローカルに git clone した
+ npm install した
+ 必要部分を修正して make test が通るようにした
+ package.json のバージョン番号を 1.0.7 にした
+ README.md のバージョン番号相当部分を 1.0.7 にした
+ git push した
+ GitHub でリリースを作成した
+ npm adduser でログイン情報を登録した
+ npm publish した

 $ node
 > new Date(Date.UTC(2016,3,8,-9))
 Fri Apr 08 2016 00:00:00 GMT+0900 (JST)

のように、正しく動作はすることを確かめられます。とはいえ、
これでは非常に読みづらいので、
JapaneseHolidays は jDate という関数を提供しています。

 LANG:javascript
 JapaneseHolidays.isHoliday(JapaneseHolidays.jDate(2016,3,8))); 

これは、上と同じ動作をします。

逆に、ある Date オブジェクトが日本時間で何日の何時何分を
表しているか読み取るため、getJ??? という形式の一連の
関数も提供しています。

 LANG:javascript
 var date = new Date();
 var jyear    = JapaneseHolidays.getJFullYear(date);
 var jmonth   = JapaneseHolidays.getJMonth(date);
 var jdate    = JapaneseHolidays.getJDate(date);
 var jday     = JapaneseHolidays.getJDay(date);
 var jhours   = JapaneseHolidays.getJHours(date);
 var jminutes = JapaneseHolidays.getJMinutes(date);

あともう一つ便利なユーティリティ関数として、
JapaneseHolidays.shiftDate があります。
この関数は与えられた Date を与えられた期間分だけ変化させた
値を計算して返します。期間には負の値も入れられます。

 LANG:javascript
 // 1年前
 console.log(JapaneseHolidays.shiftDate(new Date(), -1));
 // 1ヶ月後
 console.log(JapaneseHolidays.shiftDate(new Date(), 0, 1));
 // 15ヶ月後
 console.log(JapaneseHolidays.shiftDate(new Date(), 0, 15));
 // 明日
 console.log(JapaneseHolidays.shiftDate(new Date(), 0, 0, 1));
 // 100 時間後
 console.log(JapaneseHolidays.shiftDate(new Date(), 0, 0, 0, 100));

これらのユーティリティ関数の有効な使い方については、
例えば上でも紹介した jsbin のカレンダーの例をご参照ください。

 http://jsbin.com/qicazaroxu/edit?js,output

** やっぱりおかしい [#u3ebe405]

結果がタイムゾーンによらないように、今、ではなく、今日、
の判定をするように変更すべきだと思えてきました。

* コメント・質問・バグ報告 [#af0a004f]

できれば github の方へお願いします。日本語で結構です。~
https://github.com/osamutake/japanese-holidays-js/issues

よく分からなければここでも構いません。

#article_kcaptcha


Counter: 3568 (from 2010/06/03), today: 6, yesterday: 0