はじめに
「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>要素で設定できるようにしようと思うので,「別の手段」に近い形にする予定です.