moment.js - UTC yanlış tarih veriyor


97

Moment.js UTC neden her zaman yanlış tarihi gösteriyor? Örneğin, Chrome'un geliştirici konsolundan:

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

İkisi de "2013-07-17" diye geri dönecek, neden geçildiği tarih olan 18. yerine 17. dönüyor .

Ancak momentj'leri utc olmadan kullanırsam:

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

Moment.js UTC'yi kullanırken de beklediğim "2013-07-18" i geri alıyorum.

Bu, moment.js UTC'yi kullanırken doğru tarihi alamayacağımız anlamına mı geliyor?


4
Daha toString()sonra ihtiyacın olduğunu sanmıyorum format()(zaten bir dize döndürüyor).
alex

Yanıtlar:


163

Varsayılan olarak, MomentJS yerel saatte ayrıştırır. Yalnızca bir tarih dizesi (saat içermeyen) sağlanırsa, saat varsayılan olarak gece yarısı olur.

Kodunuzda, yerel bir tarih oluşturursunuz ve ardından bunu UTC saat dilimine dönüştürürsünüz (aslında, an örneğini UTC moduna geçirir ), böylece biçimlendirildiğinde ileri kaydırılır (yerel saatinize bağlı olarak) veya geriye doğru.

Yerel saat dilimi UTC + N ise (N pozitif bir sayı) ve yalnızca tarih içeren bir dizeyi ayrıştırırsanız, önceki tarihi alırsınız.

İşte bunu açıklamak için bazı örnekler (benim yerel saat farkım DST sırasında UTC + 3'tür):

>>> 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)"

Tarih-saat dizesinin UTC olarak yorumlanmasını istiyorsanız, bunu açıkça belirtmelisiniz:

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

ya da Matt Johnson'ın cevabında bahsettiği gibi, belirsizliği önlemek için biçim dizesini ikinci argüman olarak kullanarak ilk etapta bir UTC tarihi olarak ayrıştırabilir ( ve muhtemelen yapmalısınız ) moment.utc().

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

Diğer yoldan gitmek ve bir UTC tarihini yerel bir tarihe dönüştürmek için local()aşağıdaki yöntemi kullanabilirsiniz :

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

Çok teşekkürler. Yani temelde, UTC'yi kullanırken her zaman zamanı geçmeliyim veya ikinci yaklaşımınızda olduğu gibi UTC'de geçmeliyim.
BRG

Ya öyle ya da yerel saat dilimine sadık kalın. Zamanları sunucudan gönderirseniz, bunları Unix zaman damgası (X) veya belirli bir saat dilimindeki dizeler olarak ifade edebilirsiniz. Neden yine de kullanıcının yerel saat dilimi yerine UTC'yi kullanasınız (sunucuya normalleştirilmiş veri gönderme amacı dışında)?
MasterAM

1
new Date('07-18-2013 UTC')Eğer umursuyorsanız, bunun IE8'de çalışmayacağının farkında olun .
Dzmitry Lazerka

2
Bununla uzun süredir mücadele ediyorum. Bunun moment.js'nin en yaygın kullanım durumu olduğunu varsaydığım için, bunu sitelerinde gerçekten iyi açıklamaları gerekir. Çok teşekkür ederim! Cildimi gerçekten kurtardın!
WebWanderer

bu kod benim için çalışıyor: [kod] moment (strDate, 'DD / MM / YYYY h: mm A'). utc (strDate) .format ("YYYY-MM-DD SS: mm") [/ kod]
Omar Isaid

36

Her ikisi Dateve momentvarsayılan olarak tarayıcının yerel saat dilimindeki girdi dizesini ayrıştırır. Ancak Datebazen bu açıdan tutarsızdır. Dize özellikle kısa çizgiYYYY-MM-DD kullanılıyorsa veya öyleyse , yerel saat olarak yorumlayacaktır . Bunun aksine , nasıl ayrıştırıldığı konusunda her zaman tutarlı olacaktır.YYYY-MM-DD HH:mm:ssDatemoment

Sağladığınız biçimde bir giriş anını UTC olarak ayrıştırmanın doğru yolu şu şekilde olacaktır:

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

Bu belgelere bakın .

Daha sonra çıktı için farklı şekilde biçimlendirmek isterseniz, bunu yaparsınız:

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

toStringAçıkça aramanıza gerek yoktur .

Giriş formatını sağlamanın çok önemli olduğunu unutmayın. Bu olmadan 01-04-2013, tarayıcının kültür ayarlarına bağlı olarak, benzeri bir tarih 4 Ocak veya 1 Nisan olarak işlenebilir.


Yalnızca öğrenmek uğruna, konsolda: moment.utc ('2013-07-18 0:00 +0100', 'YYYY-AA-GG SS: dd') bana "2013-07-18 0:00 +0100 değerini verir " Ama jsfiddle geçenleri dislpays koştu olduğunu farklı olduğunda: Per Tem 25, 2013 01:00:00 GMT + 0100 Not 01:00:00 . Teşekkürler.
BRG

momentKonsolda bir raw çıktısı almak çok kullanışlı değil. Muhtemelen iç özelliklerinden birine bakıyorsunuz. Sonuçları kontrol etmeden önce biçimlendirmelisiniz. Örneğin moment.utc().format()veya moment().format().
Matt Johnson-Pint

Hem Tarih hem de an, girdi dizesini varsayılan olarak tarayıcının yerel saat diliminde ayrıştırır. Şu anda EDT'deyim. new Date('2010-12-12')bana Date {Sat Dec 11 2010 19:00:00 GMT-0500 (Eastern Daylight Time)}FF 38.0.5'te veriyor. Sadece "yerel saatte" nin tam olarak ne anlama geldiğini bağlamsallaştırmak için - bu durumda, " Datezaman dilimsiz bir dizenin UTC'de olduğunu varsayacak ve yerel saate göre ayrıştırılacak " anlamına gelir . d.getUTCDate()= 12ve d.getDate()=11
ruffin

1
Evet, bazı istisnalar var. ES5 (mevcut tarayıcıların çoğu) tarihleri ​​kısa çizgilerle UTC olarak yorumlar, ancak hemen hemen her şey yerel saat olarak yorumlanır. ES6, aynı dizeyi yerel saatle yorumlamak için bu davranışı değiştiriyor. Cevabı güncelledim.
Matt Johnson-Pint

Ha, evet, sadece MDN bu karşılaştım tam olarak söyleyerek ( '2012-12-12'bu bir ISO biçiminde var c / UTC b, ama 'December 12, 2012'hatta '2012/12/12'ES5 yerel saat dilimiyle işlendiğinden), ama buna beni yendik. O kadar harika ki ES6 hepsini yerel yapıyor [alaycı bir şekilde dedi]. Tarihler acıdır, (c) Tarihlerin
Gelişi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.