Date)Dateを避けるZを追加するこの章では、日付を扱うためのJavaScriptのAPI、Dateクラスについて説明します。
Dateを避けるJavaScriptのDate APIは使い勝手が悪いため、日付に関する処理にはライブラリに依存するのが最善です。一般的なライブラリには以下があります。
これらのライブラリのメリットとデメリットについては、ブログ記事“Why you shouldn’t use Moment.js…”を参照してください。
さらに、TC39はJavaScriptの新しい日付APIに取り組んでいます:temporal.
2つの重要な点があります。
ツリーシェイキングは、ライブラリのサイズを大幅に削減できます。これは、どこかにインポートされているライブラリのエクスポートのみをウェブサーバーにデプロイするテクニックです。関数はクラスよりもツリーシェイキングに適しています。
タイムゾーンのサポート:後で説明するように、Dateはタイムゾーンをサポートしていません。これは多くの落とし穴を生み出し、重要な弱点です。日付ライブラリがタイムゾーンをサポートしていることを確認してください。
UTC、Z、GMTは、似ていますが微妙に異なる時間指定方法です。
UTC(協定世界時)は、すべてのタイムゾーンの基準となる時間標準です。タイムゾーンはUTCを基準に指定されます。つまり、どの国や地域もUTCを現地時間として使用していません。
Z(ズールータイムゾーン)は、UTC+0の別名として、航空や軍事でよく使われる軍用タイムゾーンです。
GMT(グリニッジ標準時)は、一部のヨーロッパとアフリカの国で使用されるタイムゾーンです。UTCプラスゼロ時間であり、UTCと同じ時刻です。
出典
日付は次の時間標準をサポートしています。
操作によっては、これらのオプションの一部しか使用できません。たとえば、日付を文字列に変換したり、月の曜日などの時間単位を抽出したりする場合、現地時間とUTCのいずれかしか選択できません。
内部的には、日付はUTCとして保存されます。現地時間との間の変換では、必要なオフセットは日付によって決定されます。次の例では、現地時間はEurope/Parisです。
// CEST (Central European Summer Time)
assert.equal(
new Date('2122-06-29').getTimezoneOffset(), -120);
// CET (Central European Time)
assert.equal(
new Date('2122-12-29').getTimezoneOffset(), -60);日付を作成または変換する際には、使用されている時間標準に注意する必要があります。たとえば、new Date()は現地時間を使用し、.toISOString()はUTCを使用します。
> new Date(2077, 0, 27).toISOString()
'2077-01-26T23:00:00.000Z'日付は0を1月と解釈します。月の曜日は現地時間では27日ですが、UTCでは26日です。
各操作でサポートされる時間標準を文書化する
この章の残りの部分では、各操作でサポートされる時間標準が示されています。
タイムゾーンを指定できないことには、2つの欠点があります。
複数のタイムゾーンをサポートすることが不可能になります。
場所固有のバグが発生する可能性があります。たとえば、前の例は、実行場所によって異なる結果を生成します。安全を期するためには
Zまたはタイムオフセットを使用する(詳細は次のセクションを参照)。日時形式は、以下を記述します。
Date.parse()new Date()Date.prototype.toISOString()以下は、.toISOString()によって返される日時文字列の例です。
'2033-05-28T15:59:59.123Z'日時形式には次の構造があります。
日付形式:Y=年; M=月; D=日
YYYY-MM-DD
YYYY-MM
YYYY時間形式:T=セパレータ(文字列'T'); H=時; m=分; s=秒とミリ秒; Z=ズールータイムゾーン(文字列'Z')
THH:mm:ss.sss
THH:mm:ss.sssZ
THH:mm:ss
THH:mm:ssZ
THH:mm
THH:mmZ日時形式:日付形式に時間形式が続きます。
YYYY-MM-DDTHH:mm:ss.sssZZ(UTC+0)の代わりに、UTCからのタイムオフセットを指定することもできます。
THH:mm+HH:mm などTHH:mm-HH:mm などZを追加する文字列の最後にZを追加すると、日付のパースは異なる場所で異なる結果を生成しません。
Zなし:入力は1月27日(Europe/Parisタイムゾーン)、出力は1月26日(UTC)。
> new Date('2077-01-27T00:00').toISOString()
'2077-01-26T23:00:00.000Z'Zあり:入力は1月27日、出力は1月27日。
> new Date('2077-01-27T00:00Z').toISOString()
'2077-01-27T00:00:00.000Z'時間値は、1970年1月1日00:00:00 UTCからのミリ秒数によって日付を表します。
時間値を使用して日付を作成できます。
const timeValue = 0;
assert.equal(
new Date(timeValue).toISOString(),
'1970-01-01T00:00:00.000Z');日付を数値に変換すると、時間値が返されます。
> Number(new Date(123))
123順序演算子はオペランドを数値に変換します。したがって、これらの演算子を使用して日付を比較できます。
assert.equal(
new Date('1972-05-03') < new Date('2001-12-23'), true);
// Internally:
assert.equal(73699200000 < 1009065600000, true);次のメソッドは時間値を作成します。
Date.now(): number (UTC)
現在時刻を時間値として返します。
Date.parse(dateTimeStr: string): number (現地時間、UTC、タイムオフセット)
dateTimeStrを解析し、対応する時間値を返します。
Date.UTC(year, month, date?, hours?, minutes?, seconds?, milliseconds?): number (UTC)
指定されたUTC日時に対する時間値を返します。
Date.prototype.getTime(): number (UTC)
Dateに対応する時間値を返します。
Date.prototype.setTime(timeValue) (UTC)
timeValueによってエンコードされた日付にthisを設定します。
new Date(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, milliseconds?: number) (現地時間)
2つのパラメータには落とし穴があります。
monthでは、0は1月、1は2月などです。
yearが0≦year≦99の場合、1900が加算されます。
> new Date(12, 1, 22, 19, 11).getFullYear()
1912そのため、この章の他の場所では、時間単位yearを避け、常にfullYearを使用します。しかし、この場合は選択肢がありません。
例
> new Date(2077,0,27, 21,49).toISOString() // CET (UTC+1)
'2077-01-27T20:49:00.000Z'入力時刻(21)と出力時刻(20)が異なることに注意してください。前者は現地時間、後者はUTCを参照しています。
new Date(dateTimeStr: string) (現地時間、UTC、タイムオフセット)
最後にZがある場合、UTCが使用されます。
> new Date('2077-01-27T00:00Z').toISOString()
'2077-01-27T00:00:00.000Z'最後にZまたはタイムオフセットがない場合、現地時間が使用されます。
> new Date('2077-01-27T00:00').toISOString() // CET (UTC+1)
'2077-01-26T23:00:00.000Z'文字列に日付のみが含まれる場合、UTCとして解釈されます。
> new Date('2077-01-27').toISOString()
'2077-01-27T00:00:00.000Z'new Date(timeValue: number) (UTC)
> new Date(0).toISOString()
'1970-01-01T00:00:00.000Z'new Date() (UTC)
new Date(Date.now())と同じです。
日付には時間単位のゲッターとセッターがあります。たとえば
Date.prototype.getFullYear()Date.prototype.setFullYear(num)これらのゲッターとセッターは次のパターンに従います。
Date.prototype.get«Unit»()Date.prototype.set«Unit»(num)Date.prototype.getUTC«Unit»()Date.prototype.setUTC«Unit»(num)サポートされている時間単位は次のとおりです。
FullYearMonth:月(0~11)。落とし穴:0は1月などです。Date:月の曜日(1~31)Day(ゲッターのみ):曜日の番号(0~6、0は日曜日)Hours:時(0~23)Minutes:分(0~59)Seconds:秒(0~59)Milliseconds:ミリ秒(0~999)前述のパターンに従わないゲッターがもう1つあります。
Date.prototype.getTimezoneOffset()
現地時間とUTCの差を分単位で返します。たとえば、Europe/Parisの場合、-120(CEST、中央ヨーロッパ夏時間)または-60(CET、中央ヨーロッパ時間)を返します。
> new Date('2122-06-29').getTimezoneOffset()
-120
> new Date('2122-12-29').getTimezoneOffset()
-60日付の例
const d = new Date(0);Date.prototype.toTimeString() (現地時間)
> d.toTimeString()
'01:00:00 GMT+0100 (Central European Standard Time)'Date.prototype.toDateString() (現地時間)
> d.toDateString()
'Thu Jan 01 1970'Date.prototype.toString() (現地時間)
> d.toString()
'Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)'Date.prototype.toUTCString() (UTC)
> d.toUTCString()
'Thu, 01 Jan 1970 00:00:00 GMT'Date.prototype.toISOString() (UTC)
> d.toISOString()
'1970-01-01T00:00:00.000Z'次の3つのメソッドは、実際にはECMAScriptの一部ではなく、ECMAScript国際化APIの一部です。そのAPIは日付のフォーマットに関する多くの機能(タイムゾーンのサポートを含む)を持っていますが、パース機能はありません。
Date.prototype.toLocaleTimeString()Date.prototype.toLocaleDateString()Date.prototype.toLocaleString() 練習問題:日付文字列の作成
exercises/dates/create_date_string_test.mjs