"2016-02-16" neden "2016-02-16 00:00" ile aynı değil?


97

Her iki tarih dizesini de aktarmaya çalışıyorum new Date(t).

Her iki dizenin de aynı zamanı temsil etmesini bekliyorum, sonuçta, zamanı atlarsam, o günün gece yarısı olması gerekmez mi?

Ama süre

new Date("2016-02-16 00:00")

2016-02-16, gece yarısı, beklendiği gibi yerel saat,

new Date("2016-02-16")

2016-02-16, gece yarısı UTC'yi döndürür, bu yanlış veya en azından diğer dizenin ayrıştırdığı şeyi göz önüne aldığımda beklediğim gibi değil.

Zamanı yerel saat olarak veya UTC olarak döndürmek olsun, ikisinin de aynı davranışa sahip olmasını anlardım, ancak bunun gibi farklı şeyleri neden döndürdükleri çok tutarsız görünüyor.

Geçici bir çözüm olarak, karşılık gelen zaman damgası olmayan bir tarihle karşılaştığımda tutarlı bir davranış elde etmek için "00:00" ekleyebilirim, ancak bu oldukça kırılgan görünüyor.

Bu değeri 'datetime-local' türündeki bir INPUT öğesinden alıyorum, bu nedenle özellikle bir sayfa öğesi tarafından döndürülen bir değer etrafında çalışmak zorunda olmam özellikle tutarsız görünüyor.

Yanlış bir şey mi yapıyorum yoksa farklı bir şey mi yapmalıyım?


2
2016-02-16 00:00- bu hiç de geçerli zaman gibi görünmüyor. ecma-international.org/ecma-262/6.0/… , ancak Toraya koyduktan sonra bile gerçekten farklı davranıyor
zerkms

Şu anda, değerine bağlı olarak girdi öğesinden Date nesnesini tam olarak nasıl elde ediyorsunuz?
BoltClock

4
Standarda göre - "HH, mm veya ss alanları yoksa" 00 "değeri olarak kullanılır ve eksik bir sss alanının değeri" 000 "olur. Saat dilimi farkı yoksa tarih-saat yerel saat olarak yorumlanır. " --- aynı şekilde davranması gerekir.
zerkms

@BoltClock Hmm, öğenin değer alanını alıyor ve (zerkms fark ettiği gibi) bir nedenle T'yi kaldırıyor gibi görünüyor (sanırım değer, "T" nin kafa karıştırıcı olacağı bir bağlamda kullanıcıya gösteriliyor)
Michael

1
@Michael: Harika. Bunun gibi tarayıcı tuhaflıkları benim favorim. (Ya da DOM spesifikasyonu
tuhaflığı

Yanıtlar:


101

Bu ne ES5.1 şartname yapmaya diyor ki:

Eksik bir saat dilimi farkının değeri "Z" dir.

Ayrıca şöyle diyor:

İşlev ilk olarak Dize biçimini Tarih Saat Dize Biçimi'nde (15.9.1.15) belirtilen kurallara göre ayrıştırmaya çalışır. Dize bu biçime uymuyorsa, işlev herhangi bir uygulamaya özgü buluşsal yöntemlere veya uygulamaya özgü tarih biçimlerine geri dönebilir.

Biçim, Ttarih ve saat arasında bir ayırıcı gerektirdiğinden , geçerli saatler UTC'ye gider:

> new Date("2016-02-16T00:00:00")
Tue Feb 16 2016 01:00:00 GMT+0100 (CET)
> new Date("2016-02-16")
Tue Feb 16 2016 01:00:00 GMT+0100 (CET)

... node.js'de iken, geçersiz bir zaman (T ayırıcısı olmadan) uygulamaya özel yerel zamana gidiyor gibi görünüyor:

> new Date("2016-02-16 00:00:00")
Tue Feb 16 2016 00:00:00 GMT+0100 (CET)

ES6'nın bunu değiştirdiğini , dokümantasyonun aynı bölümünde şu şekilde değiştiğini unutmayın :

Saat dilimi farkı yoksa, tarih-saat yerel saat olarak yorumlanır.

Sevinci açan değişiklikler .

Düzenle

TC39'a göre , spesifikasyon, saat dilimi olmayan tarih ve saat dizileri olarak yorumlanmalıdır (ör. "2016-02-16T00: 00: 00") yerel (ISO 8601 uyarınca), ancak yalnızca tarih dizeleri (ör. "2016-02-16") UTC olarak (ISO 8601 ile tutarsız).


20
Gerçekten de değişime uğramanın sevinci. ES7 standardının yeni bir taslağında, UTC'den yerel saate geçişin bir kısmı geri alındı Yeni standart, tarihlerin saat dilimi belirtilmediği takdirde UTC olarak yorumlanması gerektiğini belirtirken, tarih saatleri, saat dilimi yoksa yerel saat olarak yorumlanmalıdır. belirtilir.
hichris123

3
Yalnızca tarih veya tarih-saat biçimlerinden bağımsız olarak her ikisi de gerçekten yerel saat olmalıdır. ISO8601 böyle çalışır. Sadece tarih formunun UTC gece yarısı olarak yorumlanması saçma, çünkü zamansız bir UTC tarihi kavramsal olarak mantıklı bile değil. ECMA tc39'da bununla ilgili hararetli bir tartışma oldu. Yerel saat için savaştım ve kaybettim. github.com/tc39/ecma262/issues/87
Matt Johnson-Pint

10

Spesifikasyonlara göre :

İşlev ilk olarak Dize biçimini Tarih Saat Dize Biçimi'nde (15.9.1.15) belirtilen kurallara göre ayrıştırmaya çalışır. Dize bu biçime uymuyorsa, işlev herhangi bir uygulamaya özgü buluşsal yöntemlere veya uygulamaya özgü tarih biçimlerine geri dönebilir.

Ve Tarih Saat Dize Biçimleri2016-02-16 geçerli bir tarih olarak kabul edilir

Bu biçim yalnızca tarih içeren formları içerir:

YYYY
YYYY-AA
YYYY-AA-GG

[...] HH, mm veya ss alanları yoksa, değer olarak "00" kullanılır ve eksik bir sss alanının değeri "000" olur. Eksik bir saat dilimi farkının değeri "Z" dir.

Böylece 2016-02-16çevirir 2016-02-16T00:00:00.000Z.

Diğer tarih 2016-02-16 00:00biçime uygun değildir ve bu nedenle ayrıştırması uygulamaya özgüdür. Görünüşe göre, bu tür tarihler yerel saat dilimine sahip olarak kabul edilir ve örnek tarihiniz saat dilimine bağlı olarak farklı değerler döndürür:

/* tz = +05:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-15T19:00:00.000Z
/* tz = -08:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-16T08:00:00.000Z

Özet:

  • Tarih ve saat biçimlerine uymak için davranış iyi tanımlanmıştır - saat dilimi farkı olmadığında tarih dizesi UTC (ES5) veya yerel (ES6) olarak değerlendirilir.
  • Uygun olmayan tarih ve saat biçimleri için davranış uygulamaya özeldir - saat dilimi farkı olmadığında olağan davranış tarihi yerel olarak ele almaktır.
  • Aslında uygulama, uygun olmayan tarihleri ​​ayrıştırmaya çalışmakNaN yerine geri dönmeyi seçebilir . Kodunuzu Internet Explorer 11'de test etmeniz yeterlidir;)

7

Belki de ES5, ES6 uygulamaları ve beklenen sonucunuz arasında bir farkla karşılaşıyorsunuz. Başına Date.parse MDN'yi de, 2015/10/12 00:00:00 "NaN UTC ya da yerel saatle olarak ayrıştırılamaz olabilir '' Özellikle gibi dizeleri farklı ECMAScript uygulamaları üzerinden" önemlidir.

Firefox 44 ve IE 11'deki ek testler, her ikisinin de bir tarih nesnesi döndürdüğünü ortaya çıkardı new Date("2016-02-16 00:00"); bu nesne, bir tarih bileşeni değeri almaya çalışırken NaN döndürür ve toString değeri "Geçersiz Tarih" ("NaN" değil). Bu nedenle, "tutarlı davranış elde etmek için 00:00" eklemek, farklı tarayıcılarda kolayca bozulabilir.

Diğer yanıtlarda belirtildiği gibi, new Date("2016-02-16")varsayılan olarak sıfır saat dilimi farkı kullanır ve yerel yerine gece yarısı UTC üretir.


OP aynı uygulamada farklı sonuçlar alıyor gibi görünüyor.
Salman A

6

DateParser::Parse()Chrome için V8 kaynak kodları başına .

ES5 ISO 8601 tarihleri:

[('-'|'+')yy]yyyy[-MM[-DD]][THH:mm[:ss[.sss]][Z|(+|-)hh:mm]]

İmzasız bir sayı ve ardından ':' bir zaman değeridir ve TimeComposer'a eklenir.

saat dilimi, eksikse varsayılan olarak Z'dir

> new Date("2016-02-16 00:00")
  Tue Feb 16 2016 00:00:00 GMT+0800 (China Standard Time)

Her iki biçimle de eşleşen bir dize (örneğin 1970-01-01) bir ES5 tarih-saat dizesi olarak ayrıştırılacaktır - bu, varsayılan olarak UTC time-zone şeklinde olacağı anlamına gelir . ES5 spesifikasyonunu takip ediyorsanız bu kaçınılmazdır.

> new Date("2016-02-16")
Tue Feb 16 2016 08:00:00 GMT+0800 (China Standard Time)

3

2016-02-16, gece yarısı UTC'yi döndürür, bu yanlış veya en azından diğer dizenin ayrıştırdığı şeyi göz önüne aldığımda beklediğim gibi değil.

Saat dilimi uzaklığını 00:00

new Date("2016-02-16") çıktılar Tue Feb 16 2016 05:30:00 GMT+0530 (India Standard Time)

Saat dilimim bir ofset değeriyle (dakika cinsinden) IST +330olduğundan, 00: 00'a 330 dakika ekledi.

Gereğince ECMA-262, bölüm 20.3.3.2 Date.parse (string)

ToString aniden tamamlanmaya neden olursa, Tamamlama Kaydı hemen geri gönderilir. Aksi takdirde, parse sonuçta elde edilen String'i tarih ve saat olarak yorumlar; tarih ve saate karşılık gelen UTC zaman değeri olan bir Sayı döndürür. Dize, Dize içeriğine bağlı olarak bir yerel saat, bir UTC saati veya başka bir zaman diliminde bir saat olarak yorumlanabilir.

Zaman birimlerini açıkça ayarladığınızda, new Date("2016-02-16 00:00")bunu hoursve olarak ayarlayın minutes,

Aksi takdirde , burada 2 0.3.1.16'da belirtildiği gibi

Saat dilimi farkı yoksa, tarih-saat yerel saat olarak yorumlanır.


Evet ama neden bunu bir durumda yapıp diğerinde yapmıyor?
Michael


Öyleyse neden bunlar farklı sonuçlar? Standart, aynı olması gerektiğini iddia ediyor
zerkms

@zerkms Standard, zaman birimlerini geçtiğinizde ne yapacağını söylüyor, yapmayacağınız zaman ne yapacağını söylemiyor. Açıkça, The String may be interpreted as a local time, a UTC time, or a time in some other time zone, depending on the contents of the String.aynı olması gerektiğini nerede iddia ediyor?
gurvinder372

@ gurvinder372 Soru yorumlarında alıntıyı sağladım: "HH, mm veya ss alanları yoksa değer olarak" 00 "kullanılır ve eksik bir sss alanının değeri" 000 "ise. Saat dilimi uzaklığı yoksa tarih-saat yerel saat olarak yorumlanır. "
zerkms
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.