new Date () działa w przeglądarce Chrome, ale nie Firefox

93

Tworzę ciąg daty i godziny, który wygląda następująco: 2010-07-15 11:54:21

Z poniższym kodem otrzymuję nieprawidłową datę w Firefoksie, ale działa dobrze w Chrome

var todayDateTime = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + seconds;
var date1 = new Date(todayDateTime);

W przeglądarce Firefox data1 podaje mi nieprawidłową datę, ale w chrome działa dobrze, jaka byłaby główna przyczyna?

pixeldev
źródło
2
jeśli chcesz się nim bawić w dowolny sposób, idź z datejs.com
Sinan.
Nie wszystkie implementacje obsługują format w ECMA-262, więc zawsze ręcznie analizuj ciągi (biblioteka może pomóc, ale prawdopodobnie nie jest konieczna w przypadku pojedynczych formatów).
RobG,
Teraz działa Firefox.
Sm Yamashita

Odpowiedzi:

80

Nie możesz utworzyć wystąpienia obiektu daty w dowolny sposób. Musi być w określony sposób. Oto kilka ważnych przykładów:

new Date() // current date and time
new Date(milliseconds) //milliseconds since 1970/01/01
new Date(dateString)
new Date(year, month, day, hours, minutes, seconds, milliseconds)

lub

d1 = new Date("October 13, 1975 11:13:00")
d2 = new Date(79,5,24)
d3 = new Date(79,5,24,11,33,0)

Chrome musi być po prostu bardziej elastyczny.

Źródło: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Z komentarza apsillerów :

specyfikacja EMCAScript wymaga dokładnie jednego formatu daty (np. RRRR-MM-DDTHH: mm: ss.sssZ), ale niestandardowe formaty daty mogą być swobodnie obsługiwane przez implementację : „ Jeśli ciąg znaków nie jest zgodny z formatem [zdefiniowanym przez ECMAScript] funkcja może powrócić do dowolnej heurystyki specyficznej dla implementacji lub formatów daty specyficznych dla implementacji. „Chrome i FF mają po prostu różne„ formaty daty specyficzne dla implementacji ”.

Chris Laplante
źródło
4
Mam rozwiązanie, które działa we wszystkich przeglądarkach, w tym Firefox: stackoverflow.com/a/21984717/586051
Rahul Desai,
7
Skąd ta różnica między przeglądarkami: specyfikacja EMCAScript wymaga dokładnie jednego formatu daty (tj. YYYY-MM-DDTHH:mm:ss.sssZ), Ale implementacja może swobodnie obsługiwać niestandardowe formaty daty : „ Jeśli ciąg znaków nie jest zgodny z formatem [zdefiniowanym przez ECMAScript], funkcja może korzystać z dowolnej heurystyki lub formatów dat specyficznych dla implementacji. „Chrome i FF mają po prostu różne„ formaty dat specyficzne dla implementacji ”.
apsillers
Przykład formatu daty (miesiąc zawierający znak „.”), Który działa w przeglądarce Chrome, ale nie w przeglądarce Firefox: „Luty. 14, 2019 '
codecribblr
To działało dla mnie tylko w Firefoksie, jeśli dodałem 'do milisekund, w Date('milliseconds')przeciwnym razie otrzymałem błąd mówiący, że milisekundy nie zostały zdefiniowane, ale zadziałało przynajmniej tam, gdzie wiele innych prób zakończyło się niepowodzeniem. W Chrome nadal wydaje się szczęśliwy.
Steve
24

Działa to we wszystkich przeglądarkach -

nowa data („2001/01/31 12:00:00 AM”)

new Date('2001-01-31 12:00:00')

Format: RRRR-MM-DDTHH: mm: ss.sss

Szczegóły: http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15

Tahin Rahman
źródło
ponieważ wszyscy wiemy, że to międzynarodowy standard. w3.org/International/questions/qa-date-format
Bobby Tables
6
Więc faktycznie przetestowałeś wszystkie przeglądarki ? Zakładając, że tak, wiesz też, że wszystkie przeglądarki w przyszłości będą również obsługiwać ten (niestandardowy) format?
RobG
1
To działa dla mnie. Więc jeśli otrzymałeś już ciąg „2001-1-31 12:00:00”, możemy po prostu zrobić: new Date (str.replace (/ - / g, „/”));
Jianwu Chen
@JianwuChen Celowo modyfikujesz standardowy format na niestandardowy. Nie jest to dobry pomysł.
JJJ
2
Po 3 latach nie działa w Edge i Window Safari.
Mg Thar
13

Opcja 1 :

Załóżmy, że Twój chronometraż ma następujący format:

'2016-03-10 16:00:00.0'

W takim przypadku możesz zrobić proste wyrażenie regularne, aby przekonwertować je na ISO 8601:

'2016-03-10 16:00:00.0'.replace(/ /g,'T')

To dałoby następujący wynik:

'2016-03-10T16:00:00.0'

Jest to standardowy format daty i godziny, obsługiwany przez wszystkie przeglądarki:

document.body.innerHTML = new Date('2016-03-10T16:00:00.0') // THIS IS SAFE TO USE

Opcja 2 :

Załóżmy, że Twój chronometraż ma następujący format:

'02-24-2015 09:22:21 PM'

Tutaj możesz wykonać następujące wyrażenie regularne:

'02-24-2015 09:22:21 PM'.replace(/-/g,'/');

To również tworzy format obsługiwany przez wszystkie przeglądarki:

document.body.innerHTML = new Date('02/24/2015 09:22:21 PM') // THIS IS SAFE TO USE

Wariant 3:

Załóżmy, że masz ciąg czasu, który nie jest łatwy do dostosowania do jednego z dobrze obsługiwanych standardów.

W takim przypadku najlepiej po prostu podzielić ciąg czasu na różne części i użyć ich jako indywidualnych parametrów do Date:

document.body.innerHTML = new Date(2016, 2, 26, 3, 24, 0); // THIS IS SAFE TO USE

John Slegers
źródło
1
var d = nowa data ('2017-08-28 08:02 PM' .replace (/ - / g, '/')); To doskonale działa dla mnie w chrome, a także w mozilli.
Rahul Mankar
13

Działa to również w większości przeglądarek

new Date('2001/01/31 12:00:00')

To jest format

"yyyy/MM/dd HH:mm:ss"
Alvis
źródło
3
Nie ma gwarancji, że format będzie działał w każdej przeglądarce, a tym bardziej „we wszystkich”.
RobG,
Masz rację, odpowiedź jest oparta na moim doświadczeniu.
Alvis,
8

Jeśli nadal chcesz tworzyć datę za pomocą myślników, możesz użyć tego formatu:

var date = new Date('2013-08-31T17:00:00Z')

Ale pamiętaj, że tworzy czas według UTC. Oznacza to, że jeśli mieszkasz w strefie czasowej GMT + 3 (3 godziny przed GMT), doda to przesunięcie strefy czasowej do czasu. Zatem powyższy przykład będzie miał tę wartość, jeśli GMT + 3 (zauważ, że jest godzina 20:00, a nie 17:00):

Sat Aug 31 2013 20:00:00 GMT+0300 (FLE Standard Time)

Pamiętaj, aby dodać literę „Z” na końcu, ponieważ w przeciwnym razie Chrome i Firefox przeanalizują ciąg w inny sposób (jeden doda przesunięcie czasu, a drugi nie).

Gabrielius
źródło
1
Tak, Chrome i Firefox zachowują się inaczej, jeśli nie podasz strefy czasowej. Z ciekawości myślę, że Firefox robi to źle. Powinien przyjmować GMT, jeśli nie ma strefy czasowej. Chrome tak, Firefox nie. ecma-international.org/ecma-262/5.1/#sec-15.9.1.15
Julian Jelfs
@ JulianJelfs - „ Powinien przyjąć GMT, jeśli nie ma strefy czasowej ”, tylko dla daty (w przeciwieństwie do ISO 8601). W przypadku ciągów daty i godziny należy przyjąć lokalny (zgodny z ISO 8601). W każdym razie ręczna analiza składni jest jedynym bezpiecznym sposobem.
RobG,
5

Podczas pracy z AngularJS miałem podobny problem zarówno w Firefoksie, jak i Safari. Na przykład, jeśli data zwrócona z Angular wyglądała tak:

2014-06-02 10:28:00

używając tego kodu:

new Date('2014-06-02 10:28:00').toISOString();

zwraca nieprawidłową datę w przeglądarce Firefox i Safari. Jednak w Chrome działa dobrze. Jak stwierdzono w innej odpowiedzi, Chrome jest najprawdopodobniej bardziej elastyczny dzięki analizie ciągów dat.

Moim ostatecznym celem było sformatowanie daty w określony sposób. Znalazłem doskonałą bibliotekę, która zajmowała się zarówno kwestią zgodności z różnymi przeglądarkami, jak i kwestią formatowania daty. Biblioteka nazywa się moment.js .

Korzystając z tej biblioteki, poniższy kod działa poprawnie we wszystkich testowanych przeglądarkach:

moment('2014-06-02 10:28:00').format('MMM d YY')

Jeśli chcesz dołączyć tę dodatkową bibliotekę do swojej aplikacji, możesz łatwiej zbudować swój ciąg daty, unikając możliwych problemów ze zgodnością przeglądarki. Jako bonus będziesz mieć dobry sposób na łatwe formatowanie, dodawanie, odejmowanie itp. Dat w razie potrzeby.

Migawka
źródło
Podczas analizowania łańcuchów należy zawsze przekazywać format do pliku moment.js , w przeciwnym razie po prostu zgaduje, aż znajdzie taki, który tworzy prawidłową datę.
RobG,
4

To powinno działać dla Ciebie:

var date1 = new Date(year, month, day, hour, minute, seconds);

Musiałem stworzyć datę z łańcucha, więc zrobiłem to tak:

var d = '2013-07-20 16:57:27';
var date1 = new Date(d.substr(0, 4), d.substr(5, 2), d.substr(8, 2), d.substr(11, 2), d.substr(14, 2), d.substr(17, 2));

Pamiętaj, że miesiące w javascript są od 0 do 11, więc powinieneś zmniejszyć wartość miesiąca o 1, na przykład:

var d = '2013-07-20 16:57:27';
var date1 = new Date(d.substr(0, 4), d.substr(5, 2) - 1, d.substr(8, 2), d.substr(11, 2), d.substr(14, 2), d.substr(17, 2));
Bartek Kosa
źródło
2

Proste rozwiązanie, działa ze wszystkimi przeglądarkami,

var StringDate = "24-11-2017"   
var DateVar = StringDate.split("-");
var DateVal = new Date(DateVar[1] + "/" + DateVar[0] + "/" + DateVar[2]);
alert(DateVal);
XORG_99
źródło
1

Jedna sytuacja, na którą się natknąłem, dotyczyła milisekund. FF i IE nie przeanalizują poprawnie tego ciągu daty podczas próby utworzenia nowej daty. "2014/11/24 17:38:20.177Z" Nie wiedzą, jak sobie z tym poradzić .177Z. Chrome będzie jednak działać.

bjo
źródło
1

Oto, co mi pomogło Firefoxi Chrome:

// The format is 'year-month-date hr:mins:seconds.milliseconds'
const d = new Date('2020-1-4 12:00:00.999') 
// we use the `.` separator between seconds and milliseconds.

Powodzenia...

Aakash
źródło
0

W rzeczywistości Chrome jest bardziej elastyczny, aby radzić sobie z różnymi formatami ciągów. Nawet jeśli nie poznasz formatu ciągu, Chrome nadal może pomyślnie przekonwertować ciąg na datę bez błędów. Lubię to:

  var outputDate = new Date(Date.parse(inputString));

Ale w przypadku Firefoksa i Safari sprawy stają się bardziej złożone. W rzeczywistości w dokumencie Firefoksa jest już napisane: ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse )

Ciąg reprezentujący datę RFC2822 lub ISO 8601 (można użyć innych formatów, ale wyniki mogą być nieoczekiwane).

Dlatego jeśli chcesz używać Date.parse w Firefoksie i Safari, powinieneś być ostrożny. W moim przypadku używam sztuczek, aby sobie z tym poradzić. (Uwaga: nie zawsze może być poprawne we wszystkich przypadkach)

if (input.indexOf("UTC") != -1) {
  var tempInput = inputString.substr(0, 10) + "T" + inputString.substr(11, 8) + "Z";
  date = new Date(Date.parse(tempInput));
}

Tutaj najpierw konwertuje 2013-08-08 11:52:18 UTC na 2013-08-08T11: 52: 18Z , a następnie jego format jest dopasowany do słów w dokumencie Firefoksa. W tej chwili Date.parse będzie zawsze dostępne w każdej przeglądarce.

Haimei
źródło
0

Istnieje specyfikacja W3C definiująca możliwe ciągi dat, które powinny być analizowane przez każdą przeglądarkę (w tym Firefox i Safari):

Year:
   YYYY (e.g., 1997)
Year and month:
   YYYY-MM (e.g., 1997-07)
Complete date:
   YYYY-MM-DD (e.g., 1997-07-16)
Complete date plus hours and minutes:
   YYYY-MM-DDThh:mmTZD (e.g., 1997-07-16T19:20+01:00)
Complete date plus hours, minutes and seconds:
   YYYY-MM-DDThh:mm:ssTZD (e.g., 1997-07-16T19:20:30+01:00)
Complete date plus hours, minutes, seconds and a decimal fraction of a
second
   YYYY-MM-DDThh:mm:ss.sTZD (e.g., 1997-07-16T19:20:30.45+01:00)

gdzie

YYYY = four-digit year
MM   = two-digit month (01=January, etc.)
DD   = two-digit day of month (01 through 31)
hh   = two digits of hour (00 through 23) (am/pm NOT allowed)
mm   = two digits of minute (00 through 59)
ss   = two digits of second (00 through 59)
s    = one or more digits representing a decimal fraction of a second
TZD  = time zone designator (Z or +hh:mm or -hh:mm)

Zgodnie YYYY-MM-DDThh:mmTZDz przykładem 2010-07-15 11:54:21należy przekonwertować na albo 2010-07-15T11:54:21Zlub2010-07-15T11:54:21+02:00 (lub z dowolną inną strefą czasową).

Oto krótki przykład pokazujący wyniki każdego wariantu:

const oldDateString = '2010-07-15 11:54:21'
const newDateStringWithoutTZD = '2010-07-15T11:54:21Z'
const newDateStringWithTZD = '2010-07-15T11:54:21+02:00'
document.getElementById('oldDateString').innerHTML = (new Date(oldDateString)).toString()
document.getElementById('newDateStringWithoutTZD').innerHTML = (new Date(newDateStringWithoutTZD)).toString()
document.getElementById('newDateStringWithTZD').innerHTML = (new Date(newDateStringWithTZD)).toString()
div {
  padding: 10px;
}
<div>
  <strong>Old Date String</strong>
  <br>
  <span id="oldDateString"></span>
</div>
<div>
  <strong>New Date String (without Timezone)</strong>
  <br>
  <span id="newDateStringWithoutTZD"></span>
</div>
<div>
  <strong>New Date String (with Timezone)</strong>
  <br>
  <span id="newDateStringWithTZD"></span>
</div>

Tommy
źródło
-1

W przeglądarce Firefox każda nieprawidłowa data jest zwracana jako obiekt Date jako Date 1899-11-29T19:00:00.000Z, dlatego sprawdź, czy przeglądarka to Firefox, a następnie pobierz obiekt Date w postaci ciągu "1899-11-29T19:00:00.000Z".getDate(). Na koniec porównaj to z datą.

Shahrukh Azeem
źródło
To nie wyjaśnia przyczyny problemu, ale raczej jego wynik.
Rytis
-1

Użyłem następującego formatu daty i działa we wszystkich przeglądarkach.

var target_date = new Date("Jul 17, 2015 16:55:22").getTime();

var days, hours, minutes, seconds;

var countdown = document.getElementById("countdown");

remaining = setInterval(function () {

    var current_date = new Date().getTime();
    var seconds_left = (target_date - current_date) / 1000;
    days = parseInt(seconds_left / 86400);
    seconds_left = seconds_left % 86400;
    hours = parseInt(seconds_left / 3600);
    seconds_left = seconds_left % 3600;
    minutes = parseInt(seconds_left / 60);
    seconds = parseInt(seconds_left % 60);
    countdown.innerHTML = "<b>"+days + " day, " + hours + " hour, "
        + minutes + " minute, " + seconds + " second.</b>";  
}, 1000);
umesz
źródło