new Date(Date.parse("Jul 8, 2005"));
Fri Jul 08 2005 00:00:00 GMT-ORA 07: 00 (PST)
new Date(Date.parse("2005-07-08"));
Thu Jul 07 2005 17:00:00 GMT-ORA 07: 00 (PST)
De ce este cea de-a doua analiza incorectă?
Până la a 5-a ediție spec ieșit, mi-a Data.analiza
metoda a fost complet implementarea dependente (nou Data(string)
este echivalent cu Data.parse(șir)
cu excepția acestuia din urmă returnează un număr mai degrabă decât o "Data"). În cea de-a 5-a ediție spec cerința a fost adăugat pentru a sprijini o simplificată (și ușor incorectă) ISO-8601 (vezi de asemenea Ce sunt valabile Timp Data Siruri de caractere în JavaScript?). Dar altele decât că, nu a fost nu cerință pentru ce Data.analiza " / " noua Data(string)` ar trebui să accepte faptul că a trebuit să accepte orice Data#toString ieșire (fără a spune că ceea ce a fost).
Ca de ECMAScript 2017 (ediția 8), implementari au fost necesare pentru a analiza lor de ieșire pentru Data#toString și Data#toUTCString, dar format de aceste siruri de caractere nu a fost specificată.
Ca Valoare de 2019 (editia 9) format de Data#toString și Data#toUTCString, au fost specificate și (respectiv):
oferind 2 mai multe formate Data.analiza ar trebui să analizezi în mod fiabil în noile implementări (de remarcat faptul că sprijinul nu este omniprezent și implementări neconforme vor rămâne în uz pentru o perioadă de timp).
Mi-ar recomanda această dată siruri de caractere sunt analizate manual și Data constructor folosit cu an, lună și zi argumentele pentru a evita ambiguitatea:
// parse a date in yyyy-mm-dd format
function parseDate(input) {
var parts = input.split('-');
// new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
return new Date(parts[0], parts[1]-1, parts[2]); // Note: months are 0-based
}
În timpul experienței recente scris un JS interpret m-am luptat destul cu mecanismele interioare ale ECMA/JS date. Deci, m-am gândit eu'll arunca in my 2 cents aici. Sperăm că schimbul de aceste lucruri va ajuta pe alții cu orice întrebări despre diferențele dintre browsere în modul în care acestea se ocupe de date.
Toate implementarile magazin de data lor de valori pe plan intern, ca 64-bit numere care reprezintă numărul de milisecunde de 1/1/1970 UTC (GMT este același lucru ca și UTC). Datele care apar după 1/1/1970 00:00:00
sunt numere pozitive și datele anterioare sunt negative.
Prin urmare, următorul cod produce același rezultat pe toate browserele.
Date.parse('1/1/1970');
În zona de fus orar (EST), rezultatul este 18000000 pentru că's cum multe state membre sunt în 5 ore (it's doar 4 ore timpul de vară luni). Valoarea va fi diferit în diferite zone de timp. Toate browserele majore, face la fel. Aici e freca totuși. În timp ce există o oarecare variație în șirul de intrare formate care cele mai importante browsere va analiza date, au, în esență, să le interpreteze în același fel de mult ca zone de timp și de vară sunt în cauză. Cel rezista este ISO 8601 format. L's singurul format prezentate în ECMA-262 v. 5 spec special. Pentru toate celelalte formate șir, interpretarea este dependente de implementare. În mod ironic, acesta este format în cazul în care browserele pot diferi. Aici este o comparație de ieșire din Chrome vs Firefox pentru 1/1/1970 pe masina mea, folosind ISO 8601 șir format.
Date.parse('1970-01-01T00:00:00Z'); // Chrome: 0 FF: 0
Date.parse('1970-01-01T00:00:00-0500'); // Chrome: 18000000 FF: 18000000
Date.parse('1970-01-01T00:00:00'); // Chrome: 0 FF: 18000000
Date.parse('1970-01-01T00:00:00'); // 18000000
Date.parse('1970-01-01'); // 0
Deci, pentru a răspunde original asker's direct la intrebare, "AAAA-LL-ZZ" este forma scurtă a ISO 8601 format
"YYYY-MM-DDTHH:mm:ss:sssZ"`. Deci, este interpretat ca ora UTC în timp ce celălalt este interpretat ca fiind locale. Ca's de ce,
console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08")).toString());
console.log(new Date(Date.parse("Jul 8, 2005")).toString());
console.log(new Date(Date.parse("2005-07-08T00:00:00")).toString());
Linia de jos este aceasta pentru parsarea data de siruri de caractere. SINGURA ISO 8601 șir care în condiții de siguranță puteți analiza pe diferite browsere este forma lungă. Și, ÎNTOTDEAUNA utilizați "Z" specificator. Dacă faci asta în condiții de siguranță puteți merge înainte și înapoi între local și UTC.
console.log(new Date(Date.parse("2005-07-08T00:00:00Z")).toString());
Din fericire, cele mai multe browsere actuale nu trata alte formate de intrare la fel, inclusiv la cele mai frecvent utilizate '1/1/1970' și '1/1/1970 00:00:00 AM' formate. Toate din următoarele formate (și altele) sunt tratate ca ora locală de intrare în toate browserele și convertit la UTC înainte de depozitare. Astfel, făcându-le compatibile cross-browser. Ieșirea din acest cod este la fel în toate browserele în zona de fus orar.
console.log(Date.parse("1/1/1970"));
console.log(Date.parse("1/1/1970 12:00:00 AM"));
console.log(Date.parse("Thu Jan 01 1970"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00"));
console.log(Date.parse("Thu Jan 01 1970 00:00:00 GMT-0500"));
Pe partea de ieșire, toate browserele traduce zone de timp la fel, dar ei se ocupa de coarde formate în mod diferit. Aici sunt toString funcțiile și ceea ce au de ieșire. Observa
toUTCString " și " toISOString funcțiile de ieșire 5:00 AM pe masina mea.
Convertește de la UTC la ora Locală înainte de imprimare
- toString
- toDateString
- toTimeString
- toLocaleString
- toLocaleDateString
- toLocaleTimeString
Amprentele stocate ora UTC direct
- toUTCString
- toISOString
În ChrometoString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time) toDateString Thu Jan 01 1970 toTimeString 00:00:00 GMT-05:00 (Eastern Standard Time) toLocaleString 1/1/1970 12:00:00 toLocaleDateString 1/1/1970 toLocaleTimeString 00:00:00
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
În Firefox
toString Thu Jan 01 1970 00:00:00 GMT-05:00 (Eastern Standard Time)
toDateString Thu Jan 01 1970
toTimeString 00:00:00 GMT-0500 (Eastern Standard Time)
toLocaleString Thursday, January 01, 1970 12:00:00 AM
toLocaleDateString Thursday, January 01, 1970
toLocaleTimeString 12:00:00 AM
toUTCString Thu, 01 Jan 1970 05:00:00 GMT
toISOString 1970-01-01T05:00:00.000Z
În mod normal, eu nu't de a folosi format ISO pentru șirul de intrare. Singurul moment în care utilizează acest format este benefic pentru mine este atunci când datele trebuie să fie sortate ca siruri de caractere. Formatul ISO este sortable ca-este, în timp ce altele nu sunt. Dacă trebuie să aveți compatibilitate cross-browser, fie să specificați zona de fus orar sau de a folosi un compatibile șir format. Codul noua Data('12/4/2013').toString()` trece prin următoarele interne pseudo-transformare:
"12/4/2013" -> toUCT -> [storage] -> toLocal -> print "12/4/2013"
Sper că acest răspuns a fost de ajutor.
Există o metodă de nebunie. Ca o regulă generală, dacă un browser poate interpreta o data ca un ISO-8601, se va. "2005-07-08" se încadrează în această tabără, și așa este analizat ca UTC. "Jul 8, 2005" nu poate, și de aceea este analizat în ora locală.
A se vedea JavaScript și Date, Ce Mizerie! pentru mai multe.
O altă soluție este de a construi un tablou asociativ cu formatul de dată și apoi formatați datele.
Această metodă este utilă pentru data formatat într-un unussual mod.
Un exemplu:
mydate='01.02.12 10:20:43':
myformat='dd/mm/yy HH:MM:ss';
dtsplit=mydate.split(/[\/ .:]/);
dfsplit=myformat.split(/[\/ .:]/);
// creates assoc array for date
df = new Array();
for(dc=0;dc<6;dc++) {
df[dfsplit[dc]]=dtsplit[dc];
}
// uses assc array for standard mysql format
dstring[r] = '20'+df['yy']+'-'+df['mm']+'-'+df['dd'];
dstring[r] += ' '+df['HH']+':'+df['MM']+':'+df['ss'];
Potrivit http://blog.dygraphs.com/2012/03/javascript-and-dates-what-mess.html formatul "yyyy/mm/dd" rezolvă problemele obișnuite. El spune: "Stick la "YYYY/MM/DD" pentru data de șiruri de câte ori este posibil. L's universal acceptate și lipsite de ambiguitate. Cu acest format, toate orele sunt locale." Am've set de teste:
Acest format:Folosi moment.js pentru a analiza datele:
var caseOne = moment("Jul 8, 2005", "MMM D, YYYY", true).toDate();
var caseTwo = moment("2005-07-08", "YYYY-MM-DD", true).toDate();
Al 3-lea argument determină strict de parsare (disponibil ca 2.3.0). Fără ea moment.js pot, de asemenea, da rezultate incorecte.
În timp ce CMS este corect care trece siruri de caractere în analiza metodă este, în general, nesigure, noua ECMA-262 5-a Ediție (aka ES5) caietul de sarcini la secțiunea 15.9.4.2 sugerează că Data.parse ()
, de fapt, ar trebui să se ocupe ISO-formatat date. Vechea specificație a făcut nici o astfel de cerere. Desigur, browserele vechi și unele browsere actuale încă nu oferă acest ES5 funcționalitate.
Al doilea exemplu e't greșit. Este data specificată în UTC, ca implicite de Data.prototip.toISOString()
, dar este reprezentat în zona de fus orar local.
Acest greutate redusa data de parsare biblioteca ar trebui să rezolve toate probleme similare. Îmi place la bibliotecă, pentru că este destul de ușor să se extindă. L's, de asemenea, posibil să se i18n (nu foarte drept înainte, dar nu așa de greu).
Parsarea exemplu:
var caseOne = Date.parseDate("Jul 8, 2005", "M d, Y");
var caseTwo = Date.parseDate("2005-07-08", "Y-m-d");
Și formatarea înapoi la string (veți observa ambele cazuri da exact același rezultat):
console.log( caseOne.dateFormat("M d, Y") );
console.log( caseTwo.dateFormat("M d, Y") );
console.log( caseOne.dateFormat("Y-m-d") );
console.log( caseTwo.dateFormat("Y-m-d") );
Aici este un scurt, flexibil fragment pentru a converti un datetime-șir într-un cross-browser-ul în condiții de siguranță moda ca nicel detaliate de @drankin2112.
var inputTimestamp = "2014-04-29 13:00:15"; //example
var partsTimestamp = inputTimestamp.split(/[ \/:-]/g);
if(partsTimestamp.length < 6) {
partsTimestamp = partsTimestamp.concat(['00', '00', '00'].slice(0, 6 - partsTimestamp.length));
}
//if your string-format is something like '7/02/2014'...
//use: var tstring = partsTimestamp.slice(0, 3).reverse().join('-');
var tstring = partsTimestamp.slice(0, 3).join('-');
tstring += 'T' + partsTimestamp.slice(3).join(':') + 'Z'; //configure as needed
var timestamp = Date.parse(tstring);
Browser-ul dvs. ar trebui să ofere aceeași timestamp rezultat ca `Data.analiza cu:
(new Date(tstring)).getTime()
Ambele sunt corecte, dar ele sunt interpretate ca datele cu două fusuri orare diferite. Deci ai comparat mere si portocale:
// local dates
new Date("Jul 8, 2005").toISOString() // "2005-07-08T07:00:00.000Z"
new Date("2005-07-08T00:00-07:00").toISOString() // "2005-07-08T07:00:00.000Z"
// UTC dates
new Date("Jul 8, 2005 UTC").toISOString() // "2005-07-08T00:00:00.000Z"
new Date("2005-07-08").toISOString() // "2005-07-08T00:00:00.000Z"
Am scos Data.parse()
suna de l's a folosit în mod automat pe un șir de caractere argument. De asemenea, am comparat datele folosind ISO8601 format deci, ai putea compara vizual datele între datele locale și UTC date. Ori sunt 7 ore diferenta, care este diferența de fus orar și de ce testele au arătat două date diferite.
Alt mod de a crea aceleași locale/UTC datele ar fi:
new Date(2005, 7-1, 8) // "2005-07-08T07:00:00.000Z"
new Date(Date.UTC(2005, 7-1, 8)) // "2005-07-08T00:00:00.000Z"
Dar eu încă recomand Moment.js, care este ca simplu dar puternic:
// parse string
moment("2005-07-08").format() // "2005-07-08T00:00:00+02:00"
moment.utc("2005-07-08").format() // "2005-07-08T00:00:00Z"
// year, month, day, etc.
moment([2005, 7-1, 8]).format() // "2005-07-08T00:00:00+02:00"
moment.utc([2005, 7-1, 8]).format() // "2005-07-08T00:00:00Z"
De acceptat răspunsul de la CMS este corect, am adăugat câteva caracteristici :
// parse a date time that can contains spaces, dashes, slashes, colons
function parseDate(input) {
// trimes and remove multiple spaces and split by expected characters
var parts = input.trim().replace(/ +(?= )/g,'').split(/[\s-\/:]/)
// new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
return new Date(parts[0], parts[1]-1, parts[2] || 1, parts[3] || 0, parts[4] || 0, parts[5] || 0); // Note: months are 0-based
}