はじめに
「FlaskとHerokuでタイムズカープラス最安プラン選択アプリを作る」の日時入力にdatetime-local
を使っているのですが,初期表示を与える処理をJavaScriptで書きました.そのメモを残しておきます.
日時を15分単位で丸める
タイムズカープラスでは,15分単位で料金が設定されています.貸出開始時刻も返却予定時刻も,X時00分,15分,30分,45分のいずれかから選びます.15分よりも細かい表示は必要ありません.
そこで,現在の時刻を15分単位で丸めます.
var date = new Date();
date.setMinutes(Math.round(date.getMinutes() / 15) * 15);
念の為,処理前と処理後の「分」を書いておきます.
date.getMinutes() | Math.round(date.getMinutes() / 15) * 15 |
---|---|
0〜 7 | 0 |
8〜22 | 15 |
23〜37 | 30 |
38〜52 | 45 |
53〜59 | 60 |
丸めた日時を表示させる
datetime-local
についてのMDNの記述を読むと,value
属性に,yyyy-mm-ddThh:MM
と言うフォーマットで日時を与えれば,表示できるとわかります.
また,
JavaScriptの
Date
には、数値の日時情報を正しく整形された文字列に変換したり、手動で行ったりするメソッドがいくつかあります。例えば、この用途ではDate.toISOString()
メソッドが利用できます。
と書いてあるのですが,toISOString()
で得られるタイムゾーンは常に 0 UTCオフセットのため,そのままでは使えません.
そこで,getTimezoneOffset()
を使ってUTCオフセットを分単位で取得し,マイナスしてから文字列にします.
<input type="datetime-local" name="foo" />
window.onload = function() {
var date = new Date();
date.setMinutes(Math.round(date.getMinutes() / 15) * 15
- date.getTimezoneOffset());
var foo = document.querySelector('input[name="foo"]');
foo.value = date.toISOString().substr(0, 16);
}
一応これでできるのですが,date
が表す日時を,先頭16文字を取得するためだけにずらしてしまっているので,なんか気持ち悪いです.
toLocaleString()
あたりを使えば良いのかもしれませんが,フォーマットが環境依存で安定しません.
別の手段
原始的(?)ですが,手でフォーマットを整えるやり方もあります.結局こういう感じにしておくのがラクなのかも.
<input type="datetime-local" name="foo" />
window.onload = function() {
var date = new Date();
date.setMinutes(Math.round(date.getMinutes() / 15) * 15);
var yyyy = ('0000' + date.getFullYear()).slice(-4);
var mm = ('00' + (date.getMonth() + 1)).slice(-2);
var dd = ('00' + date.getDate()).slice(-2);
var hh = ('00' + date.getHours()).slice(-2);
var MM = ('00' + date.getMinutes()).slice(-2);
var foo = document.querySelector('input[name="foo"]');
foo.value = yyyy + '-' + mm + '-' + dd + 'T' + hh + ':' + MM;
}
おわりに
最終的にはdatetime-local
は使わず,年月日時分それぞれを<select>
要素で設定できるようにしようと思うので,「別の手段」に近い形にする予定です.