2014年12月31日に設定された新しいDate()は、代わりに12月1日を示します


80

文字列をDateオブジェクトに変換しようとしていますが、オブジェクトによって31日ではなく12月1日と表示されている12月31日を除いて、すべての日で機能します。理由がわかりません。これが私のJavaScriptコードです:

var dt = new Date();
dt.setDate("31");
dt.setMonth("11");
dt.setFullYear("2014");

しかし、私の変数値は次のとおりです。

Mon Dec 01 2014 11:48:08 GMT+0100 (Paris, Madrid)

他の日付でも同じことを行うと、オブジェクトは適切な値に戻ります。私が何を間違えたのか分かりますか?


7
文字列ではなく、整数をsetMonthなどに渡すことを目的としています。
funkybro 2014

15
あなたが使用することができDate、直接コンストラクタのパラメータを:new Date(2014, 11, 31)
pomeh

9
ところで。11月は11月ではないですか?
jnovacho 2014


5
月があるため@JuhaUntinenありませんが、日付が混同されて、今だけ30日を持っています。
リスター氏2014

回答:


85

setMonth 前にすべき setDate:( 31日未満の月は安全ではありません

var dt = new Date();
dt.setFullYear(2014);
dt.setMonth(11);
dt.setDate(31);

また、setMonthの2番目のパラメータを使用して日付を設定することもできます。

var dt = new Date();
dt.setFullYear(2014);
dt.setMonth(11, 31);


コンストラクターに引数が指定されていない場合、コンストラクターはシステム設定に従って現在の日付と時刻を使用ます。

したがって、setMonthとをsetDate別々に使用すると、予期しない結果が発生します。

設定された値が論理範囲よりも大きい場合、値は隣接する値に自動調整されます

たとえば、今日がの2014-09-30場合、

var dt = new Date();
dt.setFullYear(2014); /* Sep 30 2014 */
dt.setMonth(1);       /* Mar 02 2014, see, here the auto adjustment occurs! */
dt.setDate(28);       /* Mar 28 2014 */

これを回避するには、コンストラクターを直接使用して値を設定します。

var dt = new Date(2014, 11, 31);

1
確かに私はそれを見つけましたが、それは私には本当に意味がありません
user2859409 2014

15
@ user2859409おそらく、最初に月を設定しないと、現在の月がかかり、次の月に折り返されることがあるためです(以下のJakubの回答による)
fbstj 2014

3
31日未満の月の最初のコードブロックをお勧めすることを躊躇します。たとえば、日付を9月15日に設定したいが、今日は8月31日である場合、日付は翌月に折り返され、最終的に10月15日になります。コードの2番目のブロックの+1:これは行くためのより良い方法。2引数形式のsetMonth存在すら知りませんでした。
ルークウッドワード

10
日の前月の設定も間違っている可能性があることに注意してください。ただし、この場合はそうではありません。10月31日の場合、setMonth(10)は日付を11月31日に設定し、12月1日に折り返します。setDate(31)は12月31になります。したがって、常に2引数のsetMonth()を使用します。
フロリアンF

1
+1ですが、副作用を防ぐために2か月のオプションが望ましいことを強調しておきます。
ブライアン

120

問題は、最初に日を設定したとき、あなたはまだ今月にいるので、9月です。9月は30日しかないので:

var dt = new Date(); /* today */
dt.setDate("31"); /* 1st Oct 2014 as should be by spec */
dt.setMonth("11"); /* 1st Dec 2014 */
dt.setFullYear("2014"); /* 1st Dec 2014 */

22
+ 1-これは、8月中ずっと休眠状態にあり、9月になるとお尻に噛み付くようなバグです;)
Niet the Dark Absol

19
日で失敗例が最初にあるように、一度に日付一つのコンポーネントを設定する権利は決してありませんし、最初の月で、そして2月29日に最初の年で、おそらく。3つのフィールドすべてを同時に設定する必要があります。
ジム・ギャリソン

5
+1すると、月を最初に設定する理由が説明されるため、受け入れられる回答になるはずです。これは非常にJavaScriptのWTFです
Danubian Sailor

2
「javascriptWTF」ではなく、他の言語でも同様である必要があります。
–raidriは2014

間違った日付が設定されていると、Dateオブジェクトがスローされないのはなぜですか?
jww 2014

23

それはあなたが最初にすることは

dt.setDate(31)

これにより、現在の日付が31に設定されます。現在の月は9月で30日なので、折り返します。

この時点以降の日付を印刷すると、10月1日と表示されます。


12
面白いことに、これは彼が30日間の1か月間に試したためにポップアップしただけです。1か月後、問題なく動作しているように見えました。
Peter Remmers 2014

13

年、月、日付を同時に設定することが目的であるとすると、より長い日付コンストラクターを使用できます。

新しい日付(年、月、日、時、分、秒、ミリ秒);

[...]

少なくとも2つの引数が指定されている場合、欠落している引数は1(日が欠落している場合)または0に設定されます。

だからあなたは書くでしょう:

var dt = new Date(2014, 11, 31);

すでに確立されているように、一度に日付の一部を設定すると、オーバーフローが発生する可能性があります。

var dt = new Date(2012, 1, 29); // Feb 29 2012
dt.setFullYear(2014);           // Mar 01 2014 instead of Feb 28 2014

さらに、日付の前月を設定すると、予期しないオーバーフローが発生する可能性があります(メソッドの順序を変更することを推奨する回答は正しくありません)。

var dt = new Date(2014, 0, 31); // Jan 31 2014
dt.setFullYear(2014);           // Jan 31 2014
dt.setMonth(1);                 // Mar 03 2014 instead of Feb 28 2014
dt.setDate(1);                  // Mar 01 2014

私はこの答えが好きです、なぜならそれはあなたに正しい解決策を上部に与え、そして壊れた解決策がうまくいかない理由を説明します...
キップ

7

動作の理由とそれを回避する方法は十分に説明されています。

しかし、コードの本当のエラーは、デフォルトのコンストラクターであるnew Date()を使用すべきではないということです。コードの結果は、現在の時刻で12月13日の日付になります。これがあなたの望むものだとは思えません。年、月、日をパラメーターとして受け取るDateコンストラクターを使用する必要があります。


1
受け入れられた答えへのコメントを意図したものだと思いますか?
ダニューブセーラー2014

あんまり。「何が悪かったの?」という質問への答えです。
フロリアンF

-1

答えは、日付を設定するための正しい順序は次のとおりであることを明らかにしました:

  • setFullYear()
  • setMonth()
  • setDate()

飛躍的な年の2月29日なので、最初に年を設定することも重要であることを指摘したいと思います。


1
いいえ。注文は日付が正しく設定されることを保証するものではありません。承認され、最も投票された回答の下のコメントを参照してください。
サルマンA

1
開始日が31日で、日数が少ない(30日など)月に設定した場合、最終的には翌月になります。したがって、これだけでは十分ではありません。安全のために、月を設定する前に、日付を28以下に設定する必要があります。そして最後に、日付が高い場合は、最終値に再度設定します。
バート2014

-3
var dt = new Date();
dt.setFullYear(2014);
dt.setMonth(11);
dt.setDate(31);

文字列ではなく整数として値を渡します。正しい値を返します。


更新-上記の説明は正しくありません..主な問題は、これらの3行を適切な順序で配置する必要があることでした。


いいえ、そうではありません。Chromeコンソールでのテストは次のとおりです。vardt= new Date(); 未定義のdt.setDate(31); 1412157761255 dt.setMonth(11); 1417431761255 dt.setFullYear(2014); 1417431761255 dt 2014年12月1日月曜日12:02:41GMT + 0100(パリ、マドリード)
user2859409 2014

6
引数のタイプやシーケンスとは何の関係もありません。あなたはそれが二次的なものであるかのようにシーケンスに言及しています
...–ディー

1
そのコードは機能しますが、間違った説明をしているのはなぜですか。
ダニューブセーラー2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.