2012-04-22 13 views
18

Po pierwsze, myślę, że strefa czasowa prawdopodobnie ma coś z tym wspólnego. Jestem w EST/EDT. Testuję to również na chromium 17/linux.Konstruktor daty: argumenty liczbowe a argumenty łańcuchowe podające różne daty w niektórych przypadkach

Teraz, powiedzmy, że tworzę dwie daty tak:

// December 5 

dateFromNumbers = new Date(2020, 11, 5); 
dateFromString = new Date("2020-12-5"); 

wydaje te daty powinny mieć identyczne znaczniki czasu, a oni:

+dateFromNumbers == +dateFromString; // true 

... przynajmniej w tym przypadku . Ale w niektórych przypadkach nie:

// December 15 

dateFromNumbers = new Date(2020, 11, 15); 
dateFromString = new Date("2020-12-15"); 

+dateFromNumbers == +dateFromString; // false 

Co tu się dzieje?

dateFromNumbers; // Tue Dec 15 2020 00:00:00 GMT-0500 (EST) 
dateFromString; // Mon Dec 14 2020 19:00:00 GMT-0500 (EST) 

Wygląda dateFromString wynosi 5 godzin wcześniej niż dateFromNumbers w tym przypadku (EST to GMT - 5, jestem pewien, że jest to związane w jakiś sposób).

Wydaje się mieć wpływ na koniec miesięcy od października do grudnia. Oto skrzypce, które ułatwiają sprawdzenie, które dni się różnią (chyba, że ​​jesteś czerwono-zielony, co może być trudne do zobaczenia, moje przeprosiny).

http://jsfiddle.net/9gBfX/

Co daje?


Uwagi:

  • Można ustawić strefę czasową systemu do EST/EDT zobaczyć jsfiddle przykład jak widzę go.
  • Liczby miesięcy w Datach są oparte na zera; 11 nie jest literówką.
  • Ten problem pojawia się w każdym roku, który sprawdziłem.
+1

W twoim drugim przypadku jest 15 listopada, 2020 i 15 grudnia 2020. czy to literówka? – Habib

+0

Uruchamianie Chrome 18.0.1025.162 m, Windows, GMT +2: wyniki są powtarzalne. Ale jednoznaczne określenie czasu w reprezentacji ciągów rozwiązuje problem. Generalnie unikam dat z łańcuchów, ponieważ obsługa formatów w różnych przeglądarkach jest różna i słabo udokumentowana, milisekundy są o wiele bardziej niezawodne. – DCoder

Odpowiedz

6

Po pobycie w V8's source code:

// Specification: 
// Accept ES5 ISO 8601 date-time-strings or legacy dates compatible 
// with Safari. 
<...> 
// A string that matches both formats (e.g. 1970-01-01) will be 
// parsed as an ES5 date-time string - which means it will default 
// to UTC time-zone. That's unavoidable if following the ES5 
// specification. 

Czytając otaczającą kod, wydaje się, że ciąg data-czas zarówno miesiąc i dzień długi 2 symbole są uważane za ważny ES5 data-czas ciąg.W dalszej części parsera ES5 po analizuje daty i godziny, nie komentarz:

// Successfully parsed ES5 Date Time String. Default to UTC if no TZ given. 

W przypadku „yyyy-MM-DD”, gdy kod staje się tak daleko, parser ES5 pomyślnie analizowany cały łańcuch, więc powraca, zanim starszy parser ma szansę zlokalizować strefę czasową. W przeciwnym razie (miesiąc/dzień ma długość jednego symbolu) traktowana jest jako "starsza" data-godzina, a starszy parser radzi sobie z nią i lokalizuje ją.

2

Użycie "-" jako separatora daty dla USA powoduje pomylenie niektórych przeglądarek, niektóre wykonują arytmetyczną datę, inne zwrócą NaN, więc użyj separatora daty "/". Rozwiązaniem zorientowanym na kulturę jest użycie date.js, który jest wyjątkową obsługą daty JavaScript, która rozwiązuje problemy, takie jak wskazane (http://www.datejs.com/). Stosując metodę parse usuwa wszelkie nieporozumienia:

Date.parse("2020-12-15").toString() // yields the correct date ("Tue Dec 15 00:00:00 PST 2020"). 
+2

Spróbuj użyć "/" zamiast "-". –

+0

GGG miał rację głosując na moją odpowiedź. Powinienem to rozwinąć i już to zrobiłem. –

+0

Nie przesłałem tego jednak. –

2

sanitarną na this post, wydaje się, że konstruktor Argument string Date „s jest realizacja czuły, z powodu różnych Date.parse() implementacji przez przeglądarki.

Twoje pomiary są prawidłowe i prawdopodobnie powinieneś całkowicie unikać używania tego konstruktora, jeśli chcesz, aby twoja przeglądarka prawidłowo analizowała EST.

2

Wygląda na to, że konstruktor daty wymaga spacji zamiast "-". Jest to zalecany sposób. Sprawdź ten link:
3.3. Date and Time Specification

Choć foldingwhite przestrzeń jest dozwolona w całym Date-Time specyfikacji, zaleca się, że pojedyncza przestrzeń być stosowany w każde miejsce, które pojawia FWS (czy jest to wymagane lub opcjonalne)

sprawdź również ten link:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date

dateString: Wartość ciągu reprezentująca datę. Łańcuch powinien być w formacie rozpoznanym przez metodę parsowania (znaczniki czasu zgodne z IETF RFC 2822 ).

Próbowałem poniższy kod i zwraca true

dateFromNumbers = new Date(2020, 11, 15); 
dateFromString = new Date("2020 12 15"); 
alert(+dateFromNumbers == +dateFromString);​ 

Również jego nie jest problemem rozpocząć w październiku, ma zrobić z dwucyfrowych miesięcy. Gdyby spróbować tej samej metody z wrześniem a następnie:

dateFromNumbers = new Date(2020, 8, 15); 
dateFromString = new Date("2020-09-15"); 
alert(+dateFromNumbers == +dateFromString);​ // This returns false 

Ale jeśli mogę użyć pojedynczej cyfry na wrzesień to zwraca true

dateFromNumbers = new Date(2020, 8, 15); 
dateFromString = new Date("2020-9-15"); 
alert(+dateFromNumbers == +dateFromString);​ // This returns true 

A jeśli przestrzeń korzystanie z dwucyfrowych września to zwraca true

dateFromNumbers = new Date(2020, 8, 15); 
dateFromString = new Date("2020 09 15"); 
alert(+dateFromNumbers == +dateFromString);​//This returns true 
3

Oto uproszczona odpowiedź z innych odpowiedzi.

Data rozpoznaje różne formaty ciągów

  • niestandardowych dat
  • RFC 2282 daty
  • ES 5 daty

Większość formatów są interpretowane jako lokalne terminach

na stronie 14 RFC 2282 widzimy:

data i godzina-of-day powinien wyrażać czasu lokalnego.

Niestandardowe daty są traktowane w podobny sposób. Format

ES 5 jest interpretowane jako UTC

W section 15.9.1.15 ES 5 specyfikacji widzimy:

Wartość nieobecnego strefy czasowej offset „Z”.

"Z" oznacza czas UTC.

Dziesiątego października

ES 5 sformatowane daty wymagają dwucyfrowe miesięcy i dni. Miesiące i dni w oryginalnym poście nie są zerowe. "2020-9-9" nie jest ważną datowaną reprezentacją ES 5; jest to niestandardowy format, więc jest interpretowany w czasie lokalnym. "2020-10-10" to ważna reprezentacja daty ES 5, więc musi być interpretowana w UTC.

Możliwe obejścia

  • Nie używaj konstruktora ciąg/Date.parse!
  • Zmień znak separatora, aby format nigdy nie był zgodny z formatem ES 5.
  • Określ strefę czasową.
  • Dostosuj daty do czasu lokalnego. Jeśli mają godziny lub minuty: date.setMinutes(date.getTimezoneOffset()); (to wydaje się działać, tak).