moment.js-UTCが間違った日付を与える


93

moment.js UTCが常に間違った日付を表示するのはなぜですか。たとえば、Chromeの開発者コンソールから:

moment(('07-18-2013')).utc().format("YYYY-MM-DD").toString()
// or
moment.utc(new Date('07-18-2013')).format("YYYY-MM-DD").toString()

どちらも「2013-07-17」を返しますが、渡されたのが18ではなく17を返すのはなぜですか

しかし、utcなしでmomentjsを使用する場合:

moment(new Date('07-18-2013')).format("YYYY-MM-DD").toString()

私は取り戻す「2013年7月18日」 moment.js UTCを使用しているとき、私も期待するものです。

これは、moment.js UTCを使用するときに正しい日付を取得できないことを意味しますか?


4
toString()後で必要になるとは思いませんformat()(すでに文字列が返されます)。
アレックス、2014

回答:


157

デフォルトでは、MomentJSはローカル時間で解析します。日付文字列(時間なし)のみが指定されている場合、時間のデフォルトは午前0時です。

コードでは、ローカル日付を作成し、それをUTCタイムゾーンに変換します(実際には、インスタンスがUTCモードに切り替わります)。そのため、フォーマットすると、(ローカル時刻に応じて)前方にシフトされます。後方。

ローカルタイムゾーンがUTC + N(Nは正の数)で、日付のみの文字列を解析すると、前の日付が取得されます。

これを示すいくつかの例を次に示します(私の現地時間のオフセットは、夏時間中はUTC + 3です)。

>>> moment('07-18-2013', 'MM-DD-YYYY').utc().format("YYYY-MM-DD HH:mm")
"2013-07-17 21:00"
>>> moment('07-18-2013 12:00', 'MM-DD-YYYY HH:mm').utc().format("YYYY-MM-DD HH:mm")
"2013-07-18 09:00"
>>> Date()
"Thu Jul 25 2013 14:28:45 GMT+0300 (Jerusalem Daylight Time)"

日時文字列をUTCとして解釈したい場合は、それを明示する必要があります。

>>> moment(new Date('07-18-2013 UTC')).utc().format("YYYY-MM-DD HH:mm")
"2013-07-18 00:00"

または、マットジョンソンが彼の回答で述べているように、あいまいさを防ぐために、最初にそれをUTC日付として解析し、2番目の引数としてフォーマット文字列を含めることができます(おそらくそうする必要がありますmoment.utc()

>>> moment.utc('07-18-2013', 'MM-DD-YYYY').format("YYYY-MM-DD HH:mm")
"2013-07-18 00:00"

逆の方法でUTC日​​付をローカル日付に変換するにはlocal()、次のようにメソッドを使用できます。

>>> moment.utc('07-18-2013', 'MM-DD-YYYY').local().format("YYYY-MM-DD HH:mm")
"2013-07-18 03:00"

どうもありがとう。したがって、基本的には、UTCを使用するときは常に時間を渡すか、2番目のアプローチのようにUTCで渡す必要があります。
brg 2013

それか、ローカルのタイムゾーンに固執します。サーバーから時刻を送信する場合、それらをUnixタイムスタンプ(X)または特定のタイムゾーンの文字列として表すことができます。とにかく、ユーザーのローカルタイムゾーンの代わりにUTCを使用する理由(正規化されたデータをサーバーに送信する目的を除く)?
MasterAM 2013

1
その点に注意してくださいnew Date('07-18-2013 UTC')、あなたが気にしている場合、IE8で動作しません。
Dzmitry Lazerka 2013年

2
私はこれに長い間取り組んできました。これは彼らのサイトで実際によく説明されているはずです。どうもありがとうございます!あなたは本当に私の肌を救った!
WebWanderer 2016年

このコードは私にとっては機能します:[code] moment(strDate、 'DD / MM / YYYY h:mm A')。utc(strDate).format( "YYYY-MM-DD HH:mm")[/ code]
Omarイザイド

36

両方ともDatemomentデフォルトでブラウザのローカルタイムゾーンで入力文字列を解析します。ただしDate、これはこの点と一致しない場合があります。文字列が具体的YYYY-MM-DDハイフンを使用している場合、またはそうである場合はYYYY-MM-DD HH:mm:ss現地時間として解釈されます。とは異なりDatemoment解析方法は常に一貫しています。

入力した時刻をUTCとして指定した形式で解析する正しい方法は次のとおりです。

moment.utc('07-18-2013', 'MM-DD-YYYY')

このドキュメントを参照しください。

次に、出力用に別の方法でフォーマットする場合は、次のようにします。

moment.utc('07-18-2013', 'MM-DD-YYYY').format('YYYY-MM-DD')

toString明示的に呼び出す必要はありません。

入力フォーマットを提供することが非常に重要であることに注意してください。これがないと、01-04-2013ブラウザのカルチャ設定に応じて、のような日付がJan 4thまたはApr 1stとして処理される可能性があります。


ただ学ぶために、コンソールで:moment.utc( '2013-07-18 0:00 +0100'、 'YYYY-MM-DD HH:mm')は私に「2013-07-18 0:00 +0100 "しかし、実行されたときにjsfiddleに表示されるものは異なります。つまり、2013年7月25日木曜日01:00:00 GMT + 0100 01:00:00に注意してください。ありがとう。
brg 2013

momentコンソール上にraw を出力することはあまり役に立ちません。あなたはおそらくその内部プロパティの1つを見ているでしょう。結果を確認する前にフォーマットする必要があります。たとえばmoment.utc().format()またはmoment().format()
Matt Johnson-Pint 2013

Dateとmomentはどちらも、デフォルトでブラウザのローカルタイムゾーンで入力文字列を解析します。私は今EDTにいます。FF 38.0.5でnew Date('2010-12-12')Date {Sat Dec 11 2010 19:00:00 GMT-0500 (Eastern Daylight Time)}を与えます。「現地時間で」の意味を正確にコンテキスト化するために、この場合は、Dateタイムゾーンのない文字列がUTCであり、現地時間に解析されることを想定している」 という意味に見えますd.getUTCDate()= 12およびd.getDate()=11
ruffin

1
はい、いくつかの例外があります。ES5(最新のブラウザ)はハイフンを含む日付をUTCとして解釈しますが、それ以外のほとんどすべては現地時間として解釈されます。ES6はこの動作を変更して、同じ文字列を現地時間として解釈します。答えを更新しました。
Matt Johnson-Pint 2015年

ええ、うん、MDNでこれに遭遇し、まさにそれを言っています('2012-12-12'UTC b / cはISO形式ですが、ES5のローカルタイムゾーンで解析されること'December 12, 2012''2012/12/12'あります)。ES6がそれらをすべてローカルにするほど素晴らしい(彼は皮肉にも言った)。日付は苦痛です。(c)日付の出現
ruffin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.