JavaScriptの日付オブジェクトは常に1日休みですか?


238

私のJava Scriptアプリでは、次のような形式で日付を保存しています。

2011-09-24

上記の値を使用して新しいDateオブジェクトを作成しようとすると(別の形式で日付を取得できるため)、日付は常に1日戻ってきます。下記参照:

var doo = new Date("2011-09-24");
console.log(doo);

ログ:

Fri Sep 23 2011 20:00:00 GMT-0400 (Eastern Daylight Time)

11
JavaScriptのDateクラスは日付を表すのではなく、タイムスタンプを表します(Javaと同じ)。それを日付にするために、それはタイムゾーンを使用し、それがあなたの問題の原因です。これはGMT / UTCタイムゾーン(2011年09月24日でそれを解析して00:00 UTC)及び4時間(2011年9月23日の異なる時間帯でそれを出力する20:00 GMT-0400)。
Codo 2011

2
「無効な日付」が表示されます。「-」文字を「/」文字に置き換えて、再試行してください。または、日付をビットに分割し、コンポーネントを個別に設定します(その場合、月数から1を引きます)。
RobG、2011

@Codo-はい、いい返事です。ECMA-262 15.9.1.15が適用されます。OPは「2011-09-24T20:00:00-04:00」などを使用する必要があります。
RobG、2011

1
「Sep 24 2011」という形式で適切な日付が返されることがわかりました。説明については、こちらをご覧ください:stackoverflow.com/questions/2587345/javascript-date-parse
christurnerio

回答:


98

東部夏時間であることに注意して-4 hoursください。また、戻ってきた日の時間は20です。

20h + 4h = 24h

2011-09-24の真夜中です。タイムゾーンインジケーターなしで日付のみの文字列を指定したため、日付はUTC(GMT)で解析されました。代わりにインジケータなしの日付/時刻文字列を指定した場合(new Date("2011-09-24T00:00:00"))を指定した場合、それはローカルタイムゾーンで解析されます。(歴史的には、特に仕様が複数回変更されたために不整合がありましたが、最新のブラウザーは大丈夫です。または、タイムゾーンインジケーターを常に含めることができます。)

正しい日付を取得していますが、正しいタイムゾーンを指定したことはありません。

日付の値にアクセスする必要がある場合は、getUTCDate()またはその他のgetUTC*()関数を使用できます。

var d,
    days;
d = new Date('2011-09-24');
days = ['Sun', 'Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat'];
console.log(days[d.getUTCDay()]);

24
どのように「正しいタイムゾーンを指定」しますか?日付コンストラクタは常に日付文字列をUTCとして解釈しますが、タイムゾーンに合わせて調整します。「new Date( '2012-01-02 EDT')」を実行することもできますが、夏時間のオフセットを適用するため、前の日付に戻します。 EDTの現在のローカルタイムゾーン。追加のオフセットを適用しないでください。タイムゾーンはEDTであると言いましたが、それでも1日戻って追加のオフセットが適用されます。
AaronLS 2013年

1
@AaronLSは、EDTある夏時間(サマータイムも呼ばれる)EST1月に適用されるタイムゾーンです。
zzzzBov 2013年

1
文字列からUTCだけで作成するのが私がやりたいことなので、なぜ「正しいタイムゾーンを指定するのですか」と質問したのはなぜですか。「正しいタイムゾーンを指定したことがない」と述べた場所について。私が行うnew Date('2012-01-01 GMT')場合でも、ユーザーのローカル日付時刻に変換するときにオフセットが適用されます。
AaronLS 2013年

7
@AaronLS、get*メソッドを使用せざるを得ず、不明なタイムゾーンオフセットを含む正しい日付/時刻を返す必要がある場合は、不明なタイムゾーンオフセットを追加するだけです。d = new Date('2013-01-08 GMT'); d.setMinutes(d.getMinutes() + d.getTimezoneOffset());これにより、日付がユーザーのロケールに正規化され、.get*メソッドから返されます。期待値。その場合、.getUTC*メソッドは正しくなくなりますので、注意してください。
zzzzBov 2014

1
動作を定義して参照を提供することと、実装者が何かを正しく実装できなかった場合にそれをエスケープとして使用することには違いがあります。そして、それはだていないデータは、期待に並んでいない場合に同じ表現。
反逆の怒り2016

252

文字列を変換するJS DATEオブジェクトで発生するクレイジーなことがいくつかあります。たとえば、次の日付を指定したとします

注:以下の例は、またはであってもなくてもよいOFF ONE DAYに応じYOURタイムゾーンと現在の時刻。

new Date("2011-09-24"); // Year-Month-Day
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF.

ただし、文字列形式をMonth-Day-Yearに再配置すると...

new Date("09-24-2011");
=> // Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

別の奇妙なもの

new Date("2011-09-24");
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF AS BEFORE.

new Date("2011/09/24"); // change from "-" to "/".
=> // Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

新しい日付を作成するときに、日付「2011-09-24」のハイフンを簡単に変更できます

new Date("2011-09-24".replace(/-/g, '\/')); // => "2011/09/24".
=> // Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

「2011-09-24T00:00:00」のような日付文字列があったらどうなるでしょう

new Date("2011-09-24T00:00:00");
// => Fri Sep 23 2011 17:00:00 GMT-0700 (MST) - ONE DAY OFF.

以前と同様に、ハイフンスラッシュに変更します。何が起こるのですか?

new Date("2011/09/24T00:00:00");
// => Invalid Date

私は通常、日付形式2011-09-24T00:00:00を管理する必要があるため、これを実行します。

new Date("2011-09-24T00:00:00".replace(/-/g, '\/').replace(/T.+/, ''));
// => Sat Sep 24 2011 00:00:00 GMT-0700 (MST) - CORRECT DATE.

更新

Dateコンストラクターに個別の引数を指定すると、以下で説明するように他の有用な出力を取得できます

注:引数は、Number型またはString型にすることができます。値が混在する例を示します。

特定の年の最初の月と日を取得します

new Date(2011, 0); // Normal behavior as months in this case are zero based.
=> // Sat Jan 01 2011 00:00:00 GMT-0700 (MST)

年の最後の月と日を取得する

new Date((2011 + 1), 0, 0); // The second zero roles back one day into the previous month's last day.
=> // Sat Dec 31 2011 00:00:00 GMT-0700 (MST)

数値、文字列引数の例。ゼロベースの月が再びあるため、月は3月です。

new Date(2011, "02"); 
=> // Tue Mar 01 2011 00:00:00 GMT-0700 (MST)

同じことをしますが、1日がゼロの場合、別の結果になります。

new Date(2011, "02", 0); // again the zero roles back from March to the last day of February.
=> // Mon Feb 28 2011 00:00:00 GMT-0700 (MST)

年と月の引数にゼロの日を追加すると、前月の最終日が取得されます。負の数を続けると、別の日にロールバックできます

new Date(2011, "02", -1);
=> // Sun Feb 27 2011 00:00:00 GMT-0700 (MST)

12
これは実際に私に最も役立ちました。新しい日付を作成したときに、データの最後に.replace(/-/ g、 '\ /')。replace(/ T。+ /、 '')を追加しました。超簡単!
Devin Prejean

64
うわー-JavaScriptはひどく矛盾しています。
psparrow 2016

2
.replace()呼び出しは、今夜のピンチに本当に役立ちました。
廃止

2
はい、私はこれすべてをテストしました、そしてそれは本当に奇妙です。
chintan adatiya

27
これはすべて、基礎となるDate.parse()の動作がISO 8601に従っているためです。日付文字列がyyyy-mm-dd形式に従う場合、暗黙的なUTC 00:00を持つISO 8601であると想定されます。文字列が形式(たとえば、mm-dd-yyyyまたはハイフンの代わりにスラッシュ)から外れている場合、タイムゾーンが存在しないときにローカル時刻を使用するRFC 2822に従って、緩いパーサーにフォールバックします。確かに、これはすべての平均的な人にとって非常に不可解です。
Mizstik 2016

71

日付を正規化し、不要なオフセットを排除するには(ここでテスト:https : //jsfiddle.net/7xp1xL5m/):

var doo = new Date("2011-09-24");
console.log(  new Date( doo.getTime() + Math.abs(doo.getTimezoneOffset()*60000) )  );
// Output: Sat Sep 24 2011 00:00:00 GMT-0400 (Eastern Daylight Time)

これは同じことを達成し、@ tparteeの功績をたたえます(ここでテスト済み:https ://jsfiddle.net/7xp1xL5m/1/ ):

var doo = new Date("2011-09-24");
console.log( new Date( doo.getTime() - doo.getTimezoneOffset() * -60000 )  );

これでうまくいきました。APIから日付を処理してから並べ替え/比較する必要があったので、タイムゾーンオフセットを追加するだけでうまくいきます。
chakeda 2016年

これは、timeZoneOffsetを減算するのではなく、減算する必要があったことを除いて、私にとっては
うまくいきまし

@ErikAGriffin正のタイムゾーン、つまりGMT-0X00ではなくIE GMT + 0X00を使用していますか?
AaronLS

私は似たようなことをしました:doo.setMinutes(doo.getMinutes() + doo.getTimezoneOffset())
反逆の怒り

2
@AaronLSあなたは正しい軌道に乗っていましたが、少し間違ったロジックです。TZオフセットを補正するための正しいロジックは次のとおりです。console.log(new Date(doo.getTime()-doo.getTimezoneOffset()* -60000)); -オフセットの符号は重要であり、絶対的に取り除くことはできませんが、補正のために逆符号も必要となるため、逆符号を適用するにはオフセットに-60000を乗算します。
tpartee 2017年

28

ローカルタイムゾーンで日付の0時間を取得する場合は、個々の日付部分をDateコンストラクターに渡します。

new Date(2011,08,24); // month value is 0 based, others are 1 based.

26

文字列の末尾にスペースを追加すると、作成にUTCが使用されることを追加したいだけです。

new Date("2016-07-06")
> Tue Jul 05 2016 17:00:00 GMT-0700 (Pacific Daylight Time)

new Date("2016-07-06 ")
> Wed Jul 06 2016 00:00:00 GMT-0700 (Pacific Daylight Time)

編集:これは推奨されるソリューションではなく、代わりの答えです。何が起こっているのか非常に不明確なので、このアプローチは使用しないでください。誰かがこれをリファクタリングして誤ってバグを引き起こす可能性がある方法はいくつかあります。


末尾にスペースがある例の場合、コンソールは「無効な日付= $ 2」を返します
ブライアンリスク

1
とてもうまくいきます!新しいDate(data.Date + "").toLocaleDateString( "en-US")
Nakres

公正を期すために、これは単なる代替案であり、推奨されるソリューションではありません。
カイルシュレーダー

25

タイムゾーンの調整に関係していると思います。作成した日付はGMTで、デフォルトの時刻は午前0時ですが、タイムゾーンはEDTなので、4時間差し引かれます。これを試して確認してください:

var doo = new Date("2011-09-25 EDT");

3
これがここでの最良の答えです。プログラムで変換する代わりに、組み込みのタイムゾーンローカリゼーション文字列を使用する場合は+1100万。
blearn 2017

2
これは役に立ちます。$ scope.dat = new Date(datestring + 'EDT')のように機能します。EDTとESTの違いに注意してください。リンク
Weihui Guo

裏で何が起こっているのかはわかりませんが、問題なく動作します。
the_haystacker 2018

これは、最も単純な回答であり、コードの再フォーマットが少ないと言えます。
マイケル

ありがとう、私は私に最善の方法を検討します。
ジャンダーソンコンスタンティーノ

11

あなたの問題は特にタイムゾーンにあります。一部に注意してくださいGMT-0400-それはあなたがGMTより4時間遅れているということです。表示されている日付/時刻に4時間を追加すると、2011/09/24の真夜中になります。toUTCString()代わりにメソッドを使用してGMT文字列を取得します。

var doo = new Date("2011-09-24");
console.log(doo.toUTCString());

7

これはおそらく良い答えではありませんが、この問題に関する私の経験を共有したいと思います。

私のアプリは「YYYY-MM-DD」という形式のutc日付をグローバルに使用していますが、使用するdatepickerプラグインはjs日付のみを受け入れますが、utcとjsの両方を考慮するのは難しいです。したがって、「YYYY-MM-DD」形式の日付を日付ピッカーに渡したい場合、最初に、それを「MM / DD / YYYY」形式に変換します。moment.jsなどを使用すると、日付ピッカーに表示される日付は正しい。あなたの例のために

var d = new Date('2011-09-24'); // d will be 'Fri Sep 23 2011 20:00:00 GMT-0400 (EDT)' for my lacale
var d1 = new Date('09/24/2011'); // d1 will be 'Sat Sep 24 2011 00:00:00 GMT-0400 (EDT)' for my lacale

どうやらd1は私が欲しいものです。これが一部の人々に役立つことを願っています。


1
あなたがしたようにフォーマットを切り替えるだけで、私にとっては同じように機能しました。とても奇妙。
jAC、

5

これはループを通して私を通して、zzzBovの答えに+1します。これは、UTCメソッドを使用して私のために働いた日付の完全な変換です:

//myMeeting.MeetingDate = '2015-01-30T00:00:00'

var myDate = new Date(myMeeting.MeetingDate);
//convert to JavaScript date format
//returns date of 'Thu Jan 29 2015 19:00:00 GMT-0500 (Eastern Standard Time)' <-- One Day Off!

myDate = new Date(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate());
//returns date of 'Fri Jan 30 2015 00:00:00 GMT-0500 (Eastern Standard Time)' <-- Correct Date!

4

ということは2011-09-24 00:00:00 GMT、あなたがGMT -4にいるので20:00、前日になります。

個人的に、私2011-09-24 02:00:00はに住んでいるので、を得るGMT +2


3

OPの場合、タイムゾーンはEDTですが、スクリプトを実行するユーザーがEDTタイムゾーンであるとは限らないため、オフセットのハードコーディングが必ずしも機能するとは限りません。私が見つけたソリューションは、日付文字列を分割し、Dateコンストラクターで個別の値を使用します。

var dateString = "2011-09-24";
var dateParts = dateString.split("-");
var date = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);

JSの別の奇妙さを説明する必要があることに注意してください。月はゼロベースです。


2

私のクライアントが大西洋標準時を使用している場合、この正確な問題が発生しました。クライアントが取得した日付値は「2018-11-23」で、コードがnew Date("2018-11-23")クライアントの出力に渡した日付は前日の日付値です。日付を正規化するスニペットに示すように、ユーティリティ関数を作成して、クライアントに期待される日付を与えました。

date.setMinutes(date.getMinutes() + date.getTimezoneOffset());

var normalizeDate = function(date) {
  date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
  return date;
};

var date = new Date("2018-11-23");

document.getElementById("default").textContent = date;
document.getElementById("normalized").textContent = normalizeDate(date);
<h2>Calling new Date("2018-11-23")</h2>
<div>
  <label><b>Default</b> : </label>
  <span id="default"></span>
</div>
<hr>
<div>
  <label><b>Normalized</b> : </label>
  <span id="normalized"></span>
</div>


2

日付の個々の部分が表示目的で同じままであることを確認したいだけの場合、*タイムゾーンを変更しても、これは機能するようです:

var doo = new Date("2011-09-24 00:00:00")

そこにゼロを追加するだけです。

私のコードではこれを行います:

let dateForDisplayToUser = 
  new Date( `${YYYYMMDDdateStringSeparatedByHyphensFromAPI} 00:00:00` )
  .toLocaleDateString( 
    'en-GB', 
    { day: 'numeric', month: 'short', year: 'numeric' }
  )

コンピューターのタイムゾーンを切り替えても、日付はAPIから取得したyyyy-mm-ddの日付文字列と同じままです。

しかし、私は何かを逃していますか/これは悪い考えですか?

*少なくともクロム。これはSafariでは機能しません!この執筆時点


すると.toISOString()、1日戻ります。
vivek_23

new Date('2019/11/18 05:30:00').toISOString();私のために働いた
vivek_23 '12 / 12/19

1

より多くの変換方法を使用せずにこれを処理する最良の方法は、

 var mydate='2016,3,3';
 var utcDate = Date.parse(mydate);
 console.log(" You're getting back are 20.  20h + 4h = 24h :: "+utcDate);

日付にGMTを追加するか、追加することができます。

 var  mydateNew='2016,3,3'+ 'GMT';
 var utcDateNew = Date.parse(mydateNew);
 console.log("the right time that you want:"+utcDateNew)

ライブ:https : //jsfiddle.net/gajender/2kop9vrk/1/


1

私はこのような問題に直面しました。しかし、私の問題は、データベースから日付を取得する際のオフセットでした。

これはデータベースに格納され、UTC形式です。

2019-03-29 19:00:00.0000000 +00:00

したがって、データベースから取得して日付を確認すると、オフセットが追加され、JavaScriptに返送されます。

ここに画像の説明を入力してください

これは私のサーバーのタイムゾーンであるため、+ 05:00を追加しています。私のクライアントは+07:00の異なるタイムゾーンにいます。

2019-03-28T19:00:00 + 05:00 //これはJavaScriptで取得できるものです。

だからここに私がこの問題で何をすべきか私の解決策があります。

var dates = price.deliveryDate.split(/-|T|:/);
var expDate = new Date(dates[0], dates[1] - 1, dates[2], dates[3], dates[4]);
var expirationDate = new Date(expDate);

だから日付がサーバーから来てサーバーオフセットがあるとき、日付を分割してサーバーオフセットを削除してから日付に変換します。それは私の問題を解決します。



0

このページによれば、UTCタイムゾーンを使用して日付を作成するISO日付文字列形式を使用しています。

注:Dateコンストラクター(およびDate.parse、これらは同等)を使用して日付文字列を解析することは、ブラウザーの違いと不整合のため、強くお勧めしません。RFC 2822形式の文字列のサポートは、慣例によるものです。ISO 8601形式のサポートは、日付のみの文字列(「1970-01-01」など)がローカルではなくUTCとして扱われる点が異なります。

のようにテキストの形式を変えると、"Jan 01 1970"(少なくとも私のマシンでは)ローカルタイムゾーンが使用されます。


0

私の2セントをこのスレッドに追加しようとしています(@ paul-wintzの回答について詳しく説明しています)。

DateコンストラクターがISO 8601形式の最初の部分(日付部分)に一致する文字列を受け取ると、日付が0のUTCタイムゾーンで正確な日付変換を行うように思えます。その日付が現地時間に変換されるとき、深夜UTCが現地時間帯の早い日付である場合、日付シフトが発生する可能性があります。

new Date('2020-05-07')
Wed May 06 2020 20:00:00 GMT-0400 (Eastern Daylight Time)

日付文字列が他の「緩い」形式(「/」を使用するか、日付/月にゼロが埋め込まれていない)の場合、ローカルタイムゾーンで日付が作成されるため、日付シフトの問題はありません。

new Date('2020/05/07')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-5-07')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-5-7')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)
new Date('2020-05-7')
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)

したがって、前述のように、ISO形式の日付のみの文字列で「-」を「/」に置き換えると、簡単な修正が1つあります。

new Date('2020-05-07'.replace('-','/'))
Thu May 07 2020 00:00:00 GMT-0400 (Eastern Daylight Time)

0

yyyy-mm-ddMySql Date形式で保存するには、次の操作を行う必要があります。

const newDate = new Date( yourDate.getTime() + Math.abs(yourDate.getTimezoneOffset()*60000) );
console.log(newDate.toJSON().slice(0, 10)); // yyyy-mm-dd

-1

ログはGMTを出力するので、タイムゾーンを指定します。

var doo = new Date("2011-09-24 EST");

3
この質問にはすでにたくさんの答えがあります。とにかく質問に答えたい場合は、他の回答では答えられないような新しいことを説明する必要があります。一番上の答えは、すでにタイムゾーンの問題を非常に詳細に説明しています。
Calvin Godfrey、

この答えは、stackoverflow.com
a /

誰が彼の説明がより深いかどうか気にしています...彼のコードはまだ私のものとは異なります。鉱山はずっと単純です。そしてそうそう石クモあなたは正しいです。私の悪い。
bmacx7

-3

気にしない、GMT -0400に気づかなかった、それが日付を昨日にする

デフォルトの「時間」を12:00:00に設定しようとすることができます


ええ、私は私の答えで少し高速でした、それについて申し訳ありません。私の答えを修正しました。
ChrisH 2011

-3

以下は私のために働いた-

    var doo = new Date("2011-09-24").format("m/d/yyyy");

タイムゾーンをいじらない限り、まだ機能しません。
2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.