タイムゾーンJavaScriptなしの日付の解析


147

JavaScriptでタイムゾーンなしの日付を解析したい。私が試してみました:

new Date(Date.parse("2005-07-08T00:00:00+0000"));

2005年7月8日金曜日02:00:00 GMT + 0200(中央ヨーロッパ夏時間)を返します

new Date(Date.parse("2005-07-08 00:00:00 GMT+0000"));

同じ結果を返します

new Date(Date.parse("2005-07-08 00:00:00 GMT-0000"));

同じ結果を返します

時間を解析したい:

  1. タイムゾーンなし。

  2. コンストラクターDate.UTCまたは新しい日付(年、月、日)を呼び出さずに。

  3. 単純に文字列をDateコンストラクターに渡すだけです(プロトタイプアプローチなし)。

  4. 私はDateオブジェクトではなく、オブジェクトである必要がありStringます。


3
Date.parsebtwを省略して、文字列をDateコンストラクタに直接渡すこともできます。
ベルギ2013

1
なぜこれが必要なのかはわかりませんが、Dateには常にユーザーのローカルタイムゾーンがあるはずです。JavaScriptを、Dateのラッパーオブジェクトを使用する必要がある以外のタイムゾーンで動作させたい場合は、おそらくこれでうまくいき
HMR

1
残念ながら、DateMongoDBで日付を比較するために、オブジェクトをコピーして正しいオブジェクトを取得する必要がありました。new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())
Athlan

「2005-07-08」はタイムゾーンによって意味が異なるため、時刻なしで日付を解析する場合は、想定するタイムゾーンを指定する必要があります。2020年5月の時点で、MDNのドキュメントでは、実装の違いにより、適切な日付解析機能を使用しないようアドバイスしています。ただし、Date.parse( "2005-07-08")を使用すると、おそらく00:00 UTCの時間が返されます。一方、date-fns解析は、同じ日付文字列を解析するときに現地時間00:00を返します
Andy

回答:


106

日付は正しく解析され、ローカルのタイムゾーンに変換するのはto​​Stringだけです。

let s = "2005-07-08T11:22:33+0000";
let d = new Date(Date.parse(s));

// this logs for me 
// "Fri Jul 08 2005 13:22:33 GMT+0200 (Central European Summer Time)" 
// and something else for you

console.log(d.toString()) 

// this logs
// Fri, 08 Jul 2005 11:22:33 GMT
// for everyone

console.log(d.toUTCString())

JavaScriptのDateオブジェクトはタイムスタンプです-エポック以降のミリ秒数が含まれているだけです。Dateオブジェクトにはタイムゾーン情報がありません。このタイムスタンプが表すカレンダーの日付(日、分、秒)は、解釈(to...Stringメソッドの1つ)の問題です。

上記の例は、日付が正しく解析されていることを示しています。つまり、実際には、GMTの「2005-07-08T11:22:33」に対応するミリ秒が含まれています。


4
残念ながら、文字列ではなく日付オブジェクトを生成する必要があります。
アスラン2013

@Athlan:いくつかの説明を追加。
georg 2013

1
確認しました。解析された日付をMongoDBクエリnew Date(Date.parse("2005-07-08T11:22:33+0000"))に渡し、日付をコンストラクターを介してコピーしました:new Date(dateStart.getFullYear(), dateStart.getMonth(), dateStart.getDate())。両方のソリューション、異なる結果、2番目は正解です。返信は役に立ちました。hunlock.com/ blogs / Javascript_Dates-The_Complete_Referenceに記載されています。アップ。
アスラン2013

私にとっては完全に機能しました-.toUTCString()は、元の指定された文字列から正しい時間を私に返すチケットでした。つまり、新しいDate( "2016-08-22T19:45:00.0000000")。toUTCString()
Michael Giovanni

38
JavaScriptの日付と時刻におけるすべての悪の根は、最初の文に含まれています...ローカルのタイムゾーンに変換するのは、toStringだけです...これにおける単一の責任はどこにあるのですか?toStringメソッドは、結果を文字列化し、変換しないでください。日付を変換したい場合は、他の方法で変換する必要があります。
停泊

109

同じ問題があります。たとえば、「2016-08-25T00:00:00」のように文字列として日付を取得しますが、正しい時刻の日付オブジェクトが必要です。文字列をオブジェクトに変換するには、getTimezoneOffsetを使用します。

var date = new Date('2016-08-25T00:00:00')
var userTimezoneOffset = date.getTimezoneOffset() * 60000;
new Date(date.getTime() - userTimezoneOffset);

getTimezoneOffset()負または正の値を返します。世界のあらゆる場所で機能するには、これを差し引く必要があります。


6
私は同じ問題を抱えており、これは役に立ちました。しかし、夏時間のため、これはタイムゾーンのオフセットを処理しないことがわかりました。例:私はPSTにいるので、GMTからの現在のオフセット(3月)は-8:00ですが、5月には-7:00になります。私の解決策は計算することでしたvar userTimezoneOffset = date.getTimezoneOffset()*60000;
mmh02 2017年

3
私が完全なバカでない限り、これは実際には間違った時間を返します。getTimezoneOffset()逆方向の分数をgetTimezoneOffset()返します。現在のタイムゾーンはUTC-4ですが、正の240を返します。したがって、userTimezoneOffsetから減算する必要がありますdate.getTime()
vaindil 2018

1
私はあなたが差し引かれるべき@vaindilに同意します。wakwaのソリューションは、グリニッジの正しい側にいる場合にのみ機能します。Wakwasはそれを修正する必要があります。
Janne Harju

1
ああ!早すぎる話しました。ほとんどのタイムゾーンでは機能しません。AESTとCESTの時間をGMT時間でオフセットすると、間違った日付が返されることを確認できます。
saran3h

1
@vaindilの結果は、ローカル時刻が時刻0:00で表示されるようnew Date('2016-08-25T00:00:00Z')に操作new Date('2016-08-25T00:00:00Z')することがポイントであったと私が思うのと同じですが、このコードはありZ
ませんでし

14

私は同じ問題に出くわし、私が取り組んでいるレガシープロジェクトとその問題への対処方法について、風変わりなことを思い出しました。私はその時それを理解していなかった、そして私が自分で問題に遭遇するまで本当に気にしなかった

var date = '2014-01-02T00:00:00.000Z'
date = date.substring(0,10).split('-')
date = date[1] + '-' + date[2] + '-' + date[0]

new Date(date) #Thu Jan 02 2014 00:00:00 GMT-0600

何らかの理由で「01-02-2014」として日付を渡すと、タイムゾーンがゼロに設定され、ユーザーのタイムゾーンは無視されます。これはDateクラスのまぐれかもしれませんが、少し前に存在し、今日存在します。そしてそれはクロスブラウザで動作するようです。自分で試してみてください。

このコードは、タイムゾーンが重要なグローバルプロジェクトに実装されていますが、日付を見ている人は、それが導入された正確な瞬間を気にしていませんでした。


"Z"はJSが変換するUTCを指定するため意図的なものだと思いますが、タイムゾーンが指定されていない場合は変換できず、基本的にユーザーのタイムゾーンを想定します。いくつかの確認またはより良い説明を得たいと思います。
dlsso

7
不安定な動作はダッシュが原因です。Chrome、Firefox、IE11はすべて解釈し2014/5/312014/05/312014年5月31日(土)00:00:00 GMT-0600(山岳部夏時間) ` と解釈します(現在のタイムゾーンはMDTです)。ダッシュを付けて...すべてのブラウザは2014-05-312014年5月30日金曜日18:00:00 GMT-0600(山岳夏時間)と解釈します。奇妙なことに、では2014-5-31、Chromeは土曜日を返し、Firefoxは金曜日を返し、IE11は日付が無効であると言っています。date.replace('-','/')トリックをするかもしれないようです。
atheaos

6

Dateオブジェクト自体はとにかくタイムゾーンが含まれています、と返された結果は、デフォルトの方法で文字列に変換する効果があります。つまり、タイムゾーンなしで日付オブジェクト作成することはできません。しかし、あなたができることは、Dateあなた自身のものを作成することによってオブジェクトの振る舞いを模倣することです。ただし、これは、moment.jsなどのライブラリに渡す方が適切です。


2
残念ながら、文字列ではなく日付オブジェクトを生成する必要があります。
アスラン2013

3

簡単な解決策

const handler1 = {
  construct(target, args) {
    let newDate = new target(...args);
    var tzDifference = newDate.getTimezoneOffset();
    return new target(newDate.getTime() + tzDifference * 60 * 1000);
  }
};

Date = new Proxy(Date, handler1);

3

JavaScriptの日付は、内部を単純にしています。そのため、日時データはUTC UNIXエポック(ミリ秒またはミリ秒)で保存されます。

地球上のどのタイムゾーンでも変更されない「固定」時間にしたい場合は、現在のローカルタイムゾーンと一致するようにUTCで時間を調整して保存できます。そして、それを取得すると、ローカルタイムゾーンに関係なく、それを保存した時間に基づいて調整されたUTC時間が表示され、ローカルタイムゾーンオフセットを追加して「固定」時間を取得します。

日付を保存するには(ミリ秒)

toUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC - offset; // UTC - OFFSET
}

日付を取得/表示するには(ミリ秒)

fromUTC(datetime) {
  const myDate = (typeof datetime === 'number')
    ? new Date(datetime)
    : datetime;

  if (!myDate || (typeof myDate.getTime !== 'function')) {
    return 0;
  }

  const getUTC = myDate.getTime();
  const offset = myDate.getTimezoneOffset() * 60000; // It's in minutes so convert to ms
  return getUTC + offset; // UTC + OFFSET
}

次に、次のことができます。

const saveTime = new Date(toUTC(Date.parse("2005-07-08T00:00:00+0000")));
// SEND TO DB....

// FROM DB...
const showTime = new Date(fromUTC(saveTime));

2

このコードを使用できます

var stringDate = "2005-07-08T00:00:00+0000";
var dTimezone = new Date();
var offset = dTimezone.getTimezoneOffset() / 60;
var date = new Date(Date.parse(stringDate));
date.setHours(date.getHours() + offset);

1
これは夏時間を考慮していないと思います
Daniel Thompson

2

日付を表示するとき(たとえば、現地時間で表示するとき)は、実際にはフォーマットの問題であるため、より明示的で出力オプションが多いので、new(ish)Intl.DateTimeFormatオブジェクトを使用してフォーマットを実行します。

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };

const dateFormatter = new Intl.DateTimeFormat('en-US', dateOptions);
const dateAsFormattedString = dateFormatter.format(new Date('2019-06-01T00:00:00.000+00:00'));

console.log(dateAsFormattedString) // "June 1, 2019"

示されているように、timeZoneを「UTC」に設定すると、ローカル変換は実行されません。おまけとして、より洗練された出力を作成することもできます。Intl.DateTimeFormatオブジェクトの詳細については、Mozilla-Intl.DateTimeFormatを参照してください。

編集:

新しいIntl.DateTimeFormatオブジェクトを作成しなくても、同じ機能を実現できます。ロケールと日付のオプションをtoLocaleDateString()関数に直接渡すだけです。

const dateOptions = { timeZone: 'UTC', month: 'long', day: 'numeric', year: 'numeric' };
const myDate = new Date('2019-06-01T00:00:00.000+00:00');
today.toLocaleDateString('en-US', dateOptions); // "June 1, 2019"

1

単なる一般的なメモです。柔軟性を保つ方法。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

getMinutes()を使用できますが、最初の9分間は1つの数値しか返しません。

let epoch = new Date() // Or any unix timestamp

let za = new Date(epoch),
    zaR = za.getUTCFullYear(),
    zaMth = za.getUTCMonth(),
    zaDs = za.getUTCDate(),
    zaTm = za.toTimeString().substr(0,5);

console.log(zaR +"-" + zaMth + "-" + zaDs, zaTm)

Date.prototype.getDate()
    Returns the day of the month (1-31) for the specified date according to local time.
Date.prototype.getDay()
    Returns the day of the week (0-6) for the specified date according to local time.
Date.prototype.getFullYear()
    Returns the year (4 digits for 4-digit years) of the specified date according to local time.
Date.prototype.getHours()
    Returns the hour (0-23) in the specified date according to local time.
Date.prototype.getMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to local time.
Date.prototype.getMinutes()
    Returns the minutes (0-59) in the specified date according to local time.
Date.prototype.getMonth()
    Returns the month (0-11) in the specified date according to local time.
Date.prototype.getSeconds()
    Returns the seconds (0-59) in the specified date according to local time.
Date.prototype.getTime()
    Returns the numeric value of the specified date as the number of milliseconds since January 1, 1970, 00:00:00 UTC (negative for prior times).
Date.prototype.getTimezoneOffset()
    Returns the time-zone offset in minutes for the current locale.
Date.prototype.getUTCDate()
    Returns the day (date) of the month (1-31) in the specified date according to universal time.
Date.prototype.getUTCDay()
    Returns the day of the week (0-6) in the specified date according to universal time.
Date.prototype.getUTCFullYear()
    Returns the year (4 digits for 4-digit years) in the specified date according to universal time.
Date.prototype.getUTCHours()
    Returns the hours (0-23) in the specified date according to universal time.
Date.prototype.getUTCMilliseconds()
    Returns the milliseconds (0-999) in the specified date according to universal time.
Date.prototype.getUTCMinutes()
    Returns the minutes (0-59) in the specified date according to universal time.
Date.prototype.getUTCMonth()
    Returns the month (0-11) in the specified date according to universal time.
Date.prototype.getUTCSeconds()
    Returns the seconds (0-59) in the specified date according to universal time.
Date.prototype.getYear()
    Returns the year (usually 2-3 digits) in the specified date according to local time. Use getFullYear() instead. 

-1

(new Date().toString()).replace(/ \w+-\d+ \(.*\)$/,"")

これは出力されます:2018年7月10日火曜日19:07:11

(new Date("2005-07-08T11:22:33+0000").toString()).replace(/ \w+-\d+ \(.*\)$/,"")

出力は次のようになります。FriJul 08 2005 04:22:33

注:返される時間はローカルのタイムゾーンによって異なります


-1

これは私のために働くこの問題のために私が思いついた解決策です。


使用するライブラリ:プレーンなJavaScriptのDateクラスを持つmomentjs。

ステップ1.文字列の日付をモーメントオブジェクトに変換します(PS:toDate()メソッドが呼び出されない限り、モーメントは元の日付と時刻を保持します)。

const dateMoment = moment("2005-07-08T11:22:33+0000");

ステップ2. 以前に作成したモーメントオブジェクトから値を抽出hoursminutesます。

  const hours = dateMoment.hours();
  const mins = dateMoment.minutes();

ステップ3.モーメントを日付に変換します(PS:これにより、ブラウザー/マシンのタイムゾーンに基づいて元の日付が変更されますが、心配せずにステップ4を読んでください)。

  const dateObj = dateMoment.toDate();

ステップ4.ステップ2で抽出した時間と分を手動で設定します。

  dateObj.setHours(hours);
  dateObj.setMinutes(mins);

ステップ5。 dateObjは、タイムゾーンの違いなしに元の日付が表示されます。元の時間と分を手動で設定しているため、夏時間の変更でさえ日付オブジェクトに影響を与えません。

お役に立てれば。


-7

残念ながらデフォルトではうまく対処されていない日付の解析にはいくつかの固有の問題があります。

-人間が読める日付には暗黙のタイムゾーンがあります
ウェブでは広く使用されている日付形式があいまいです

これらの問題を簡単かつクリーンに解決するには、次のような関数が必要です。

>parse(whateverDateTimeString,expectedDatePattern,timezone)
"unix time in milliseconds"

私はこれを検索しましたが、そのようなものは何も見つかりませんでした!

だから私は作成しました:https//github.com/zsoltszabo/timestamp-grabber

楽しい!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.