Wyświetla datę / godzinę w lokalnym formacie użytkownika i przesunięcie czasu

167

Chcę, aby serwer zawsze podawał daty w formacie UTC w kodzie HTML i aby JavaScript w witrynie klienta był konwertowany na lokalną strefę czasową użytkownika.

Dodatkowa korzyść, jeśli mogę wyświetlać dane w formacie daty użytkownika.

kch
źródło

Odpowiedzi:

165

Wydaje się, że najbardziej niezawodnym sposobem rozpoczęcia od daty UTC jest utworzenie nowego Dateobiektu i użycie setUTC…metod w celu ustawienia żądanej daty / godziny.

Następnie różne toLocale…Stringmetody zapewnią zlokalizowane dane wyjściowe.

Przykład:

// This would come from the server.
// Also, this whole block could probably be made into an mktime function.
// All very bare here for quick grasping.
d = new Date();
d.setUTCFullYear(2004);
d.setUTCMonth(1);
d.setUTCDate(29);
d.setUTCHours(2);
d.setUTCMinutes(45);
d.setUTCSeconds(26);

console.log(d);                        // -> Sat Feb 28 2004 23:45:26 GMT-0300 (BRT)
console.log(d.toLocaleString());       // -> Sat Feb 28 23:45:26 2004
console.log(d.toLocaleDateString());   // -> 02/28/2004
console.log(d.toLocaleTimeString());   // -> 23:45:26

Niektóre odniesienia:

kch
źródło
1
W przeglądarce Firefox toLocateDateString()zwraca coś, co wygląda jak „Niedziela, 12 stycznia 2014 r.” ..
BlueRaja - Danny Pflughoeft
1
Hmm tak, to dość poważny problem. Korzystanie z tych metod nie zadziała, jeśli chcesz, aby data wyglądała tak samo w różnych przeglądarkach. Znane są jakieś alternatywy?
Josh Mc,
6
var d = new Date(Date.UTC(2004,1,29,2,45,26));
Jednoliniowa
4
Warto wziąć pod uwagę, że Chrome (od wersji 35) nie uwzględnia lokalizacji użytkownika w toLocaleString()funkcjach.
benno
8
Przepraszam, ale ta metoda nie działa pod (jestem w Australii), kiedy uruchamiam powyższy kod, data jest wyświetlana w formacie amerykańskim. Ponadto MDN mówi, że „używane ustawienia regionalne i forma zwracanego ciągu są całkowicie zależne od implementacji”.
tgrrr
65

W przypadku nowych projektów po prostu użyj momentu.js.

To pytanie jest dość stare, więc moment.js w tamtym czasie nie istniał, ale w przypadku nowych projektów bardzo upraszcza takie zadania.

Najlepiej przeanalizować ciąg daty z UTC w następujący sposób (utwórz na serwerze ciąg zgodny z ISO-8601, aby uzyskać spójne wyniki we wszystkich przeglądarkach):

var m = moment("2013-02-08T09:30:26Z");

Teraz po prostu użyj mw swojej aplikacji, moment.js domyślnie ustawia lokalną strefę czasową dla operacji wyświetlania. Istnieje wiele sposobów formatowania wartości daty i godziny lub wyodrębniania ich części.

Możesz nawet sformatować obiekt momentu w lokalizacji użytkownika w następujący sposób:

m.format('LLL') // Returns "February 8 2013 8:30 AM" on en-us

Aby przekształcić obiekt moment.js w inną strefę czasową (tj. Ani lokalną, ani UTC), będziesz potrzebować rozszerzenia strefy czasowej moment.js . Ta strona zawiera również kilka przykładów, jest dość prosta w użyciu.

theDmi
źródło
Jak to wszystko łączysz? Wydaje się, że m.utcOffset (offset) .format ('LLL') nie działa.
bart
Czy Luxon lub Day.js powinny być teraz sugerowaną biblioteką?
Homer
1
Proponuję dodaćFor old projects, just use jQuery
Xenos
Nie działa na Chrome - nadal pokazuje am / pm, mimo że czas jest ustawiony na 24 godziny w ustawieniach lokalnych komputera
vir nas
20

Możesz użyć new Date().getTimezoneOffset()/60dla strefy czasowej. Istnieje również toLocaleString()metoda wyświetlania daty przy użyciu ustawień regionalnych użytkownika.

Oto cała lista: Praca z datami

jop
źródło
ToLocaleString jest wyjątkowo zawodne w prezentowaniu dat w formacie, jakiego może oczekiwać użytkownik. Nawet jeśli obsługiwany jest ISO 402, nadal jest bardzo zawodny i opiera format na języku, a nie ustawieniach regionalnych.
RobG
@RobG jakie jest rozwiązanie zamiast toLocaleString?
user924
@ user924 - możesz skorzystać z biblioteki, jest z czego wybierać. Problem z toLocaleString polega na tym, że różne implementacje dają różne wyniki z różnymi poziomami obsługi różnych języków i regionów. Np. Moim domyślnym językiem systemu nie jest en-US, ale domyślnym formatem toLocaleString dla niektórych przeglądarek jest format amerykański, inne szanują mój język systemu. Tak samo jest z nazwami stref czasowych, tylko gorzej, ponieważ nie są one w ogóle znormalizowane. :-(
RobG
7

Gdy masz już skonstruowany obiekt daty, oto fragment kodu konwersji:

Funkcja przyjmuje obiekt Date w formacie UTC i ciąg formatu.
Będziesz potrzebował Date.strftimeprototypu.

function UTCToLocalTimeString(d, format) {
    if (timeOffsetInHours == null) {
        timeOffsetInHours = (new Date().getTimezoneOffset()/60) * (-1);
    }
    d.setHours(d.getHours() + timeOffsetInHours);

    return d.strftime(format);
}
simianarmy
źródło
6
skąd się strftime?
Anuj Pandey
Czy ustawienie godzin ma jakikolwiek wpływ na części Dzień / Data / Rok obiektu Date? Nie wydaje się.
ChristoKiwi,
1
@ ChristoKiwi — wartość przekazana do setHours powinna być liczbą całkowitą, getTimezoneOffset()/60może zwrócić ułamek (np. Przesunięcie Indii o +05: 30 zwróci 5,5). Liczby dziesiętne są obcinane. W przeciwnym razie ustawienie godzin spowoduje zaktualizowanie innych wartości (ustaw godziny na 48 i zobacz, co się stanie).
RobG
7

W JS nie ma prostych i wieloplatformowych sposobów formatowania lokalnej daty i godziny, poza konwersją każdej właściwości, jak wspomniano powyżej.

Oto szybki hack, którego używam, aby uzyskać lokalny RRRR-MM-DD. Zauważ, że to hack, ponieważ ostateczna data nie będzie już miała poprawnej strefy czasowej (więc musisz zignorować strefę czasową). Jeśli potrzebuję czegoś więcej, używam momentu.js.

var d = new Date();    
d = new Date(d.getTime() - d.getTimezoneOffset() * 60000)
var yyyymmdd = t.toISOString().slice(0,0); 
// 2017-05-09T08:24:26.581Z (but this is not UTC)

D.getTimezoneOffset () zwraca przesunięcie strefy czasowej w minutach, a d.getTime () w ms, stąd x 60 000.

Jeremy Chone
źródło
1
@VG Dodałem więcej informacji o tym, skąd pochodzi 60k. Mam nadzieję, że to pomoże.
Jeremy Chone
5

Oto, czego użyłem w poprzednich projektach:

var myDate = new Date();
var tzo = (myDate.getTimezoneOffset()/60)*(-1);
//get server date value here, the parseInvariant is from MS Ajax, you would need to do something similar on your own
myDate = new Date.parseInvariant('<%=DataCurrentDate%>', 'yyyyMMdd hh:mm:ss');
myDate.setHours(myDate.getHours() + tzo);
//here you would have to get a handle to your span / div to set.  again, I'm using MS Ajax's $get
var dateSpn = $get('dataDate');
dateSpn.innerHTML = myDate.localeFormat('F');
znak
źródło
4
Dotyczy to rzeczy specyficznych dla ASP.NET.
ZiggyTheHamster
Przesunięcia stref czasowych niekoniecznie muszą być nawet wielokrotnościami godziny, więc getTimezoneOffset()/60często zwracają wartość dziesiętną. Jest to szczególnie prawdziwe w przypadku dat sprzed 1900 r., Gdzie wiele miejsc miało przesunięcia w minutach i sekundach. Ponadto daty javascript są teraz wymagane do obsługi historycznych przesunięć. Np. W 1890 roku offset w Moskwie wynosił +2: 30: 17. Zobacz Przeglądarki, strefy czasowe, Chrome 67 Błąd .
RobG
3

Plik .getTimezoneOffset()Metoda zgłasza strefy czasowej w minutach liczenia „Westwards” ze strefy czasowej GMT / UTC, w wyniku czego wartość odsunięcia, która jest ujemna, co jeden jest powszechnie przyzwyczajeni. (Przykładowo, czas w Nowym Jorku zostanie zgłoszony jako +240 minut lub +4 godziny)

Aby uzyskać normalne przesunięcie strefy czasowej w godzinach, musisz użyć:

var timeOffsetInHours = -(new Date()).getTimezoneOffset()/60

Ważny szczegół:
Zwróć uwagę, że czas letni jest uwzględniany w wyniku - więc to, co daje ta metoda, to tak naprawdę przesunięcie czasu, a nie rzeczywiste przesunięcie geograficzne strefy czasowej .

Már Örlygsson
źródło
3

Z datą z kodu PHP użyłem czegoś takiego ...

function getLocalDate(php_date) {
  var dt = new Date(php_date);
  var minutes = dt.getTimezoneOffset();
  dt = new Date(dt.getTime() + minutes*60000);
  return dt;
}

Możemy to tak nazwać

var localdateObj = getLocalDate('2015-09-25T02:57:46');
hriziya
źródło
Pytanie dotyczyło JavaScript, a nie PHP.
pipedreambomb
5
Odpowiedź jest tylko w javascript. W pytaniu wspomniano, że data serwera jest w czasie UTC. więc serwer może być w dowolnym języku. więc odpowiedziałem tylko za PHP
hriziya
3

Do tej pory mieszam odpowiedzi i dodaję do nich, ponieważ musiałem je wszystkie przeczytać i dodatkowo przez chwilę zbadać, aby wyświetlić ciąg daty i czasu z db w lokalnym formacie strefy czasowej użytkownika.

Ciąg daty i godziny pochodzi z bazy danych python / django w formacie: 2016-12-05T15: 12: 24.215Z

Wiarygodne wykrywanie języka przeglądarki w JavaScript wydaje się nie działać we wszystkich przeglądarkach (zobacz JavaScript do wykrywania preferencji językowych przeglądarki ), więc otrzymuję język przeglądarki z serwera.

Python / Django: wyślij żądanie języka przeglądarki jako parametr kontekstu:

language = request.META.get('HTTP_ACCEPT_LANGUAGE')
return render(request, 'cssexy/index.html', { "language": language })

HTML: napisz to w ukrytym wejściu:

<input type="hidden" id="browserlanguage" value={{ language }}/>

JavaScript: pobierz wartość ukrytych danych wejściowych, np. En-GB, en-US; q = 0.8, en; q = 0.6 /, a następnie weź pierwszy język z listy tylko za pomocą zamiany i wyrażenia regularnego

const browserlanguage = document.getElementById("browserlanguage").value;
var defaultlang = browserlanguage.replace(/(\w{2}\-\w{2}),.*/, "$1");

JavaScript: przekonwertuj na datetime i sformatuj go:

var options = { hour: "2-digit", minute: "2-digit" };
var dt = (new Date(str)).toLocaleDateString(defaultlang, options);

Zobacz: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

Wynik to (język przeglądarki to en-gb): 12.05.2016, 14:58

Anja
źródło
3

// new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])
var serverDate = new Date(2018, 5, 30, 19, 13, 15); // just any date that comes from server
var serverDateStr = serverDate.toLocaleString("en-US", {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
})
var userDate = new Date(serverDateStr + " UTC");
var locale = window.navigator.userLanguage || window.navigator.language;

var clientDateStr = userDate.toLocaleString(locale, {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric'
});

var clientDateTimeStr = userDate.toLocaleString(locale, {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
});

console.log("Server UTC date: " + serverDateStr);
console.log("User's local date: " + clientDateStr);
console.log("User's local date&time: " + clientDateTimeStr);

Siergiej
źródło
Dla porównania: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… (potrzebowałem optionsczęści do mojego przypadku)
Xenos
2

Najlepszym rozwiązaniem, z jakim się spotkałem, jest utworzenie znaczników [time display = "llll" datetime = "UTC TIME" /] i użycie javascript (jquery) do przeanalizowania i wyświetlenia go w odniesieniu do czasu użytkownika.

http://momentjs.com/ Moment.js

ładnie wyświetli czas.

Daniel
źródło
2

Możesz użyć poniższego, który podaje przesunięcie strefy czasowej w stosunku do GMT w minutach:

new Date().getTimezoneOffset();

Uwaga: - ta funkcja zwraca liczbę ujemną.

dave
źródło
1

getTimeZoneOffset () i toLocaleString są dobre do podstawowej pracy z datami, ale jeśli potrzebujesz obsługi prawdziwej strefy czasowej, spójrz na TimeZone.js mde .

W odpowiedzi na to pytanie omówiono jeszcze kilka opcji

Eon
źródło
1

Aby przekonwertować datę na datę lokalną, użyj metody toLocaleDateString ().

var date = (new Date(str)).toLocaleDateString(defaultlang, options);

Aby przekonwertować czas na czas lokalny, użyj metody toLocaleTimeString ().

var time = (new Date(str)).toLocaleTimeString(defaultlang, options);
Codemaker
źródło
-12

Nie wiem, jak to zrobić, ale javascript jest technologią po stronie klienta.

usersLocalTime = new Date();

będzie zawierał czas i datę klienta (zgłoszone przez przeglądarkę, a co za tym idzie - komputer, na którym się znajduje). Włączenie czasu serwera do odpowiedzi i wykonanie prostych działań matematycznych w celu zgadnięcia przesunięcia czasu powinno być trywialne.

japollock
źródło