Konwertuj epokę UTC na datę lokalną

273

Od jakiegoś czasu walczę z tym. Próbuję przekonwertować epokę na obiekt daty. Epoka jest wysyłana do mnie w UTC. Ilekroć miniesz new Date()epokę, zakłada się, że to epoka lokalna. Próbowałem utworzyć obiekt UTC, a następnie setTime()dostosować go do właściwej epoki, ale jedyną metodą, która wydaje się przydatna, jest to, że toUTCString()łańcuchy mi nie pomagają. Jeśli przekażę ten ciąg w nową datę, powinien zauważyć, że jest to UTC, ale tak nie jest.

new Date( new Date().toUTCString() ).toLocaleString()

Moja kolejna próba polegała na znalezieniu różnicy między bieżącą epoką lokalną a obecną epoką UTC, ale ja też nie byłem w stanie jej uzyskać.

new Date( new Date().toUTCString() ).getTime() - new Date().getTime()

Daje mi to bardzo małe różnice, poniżej 1000, co jest w milisekundach.

Jakieś sugestie?

Shane Reustle
źródło
11
Czas epoki definiuje się jako upływ milisekund od daty 1970 w UTC . Nie ma czegoś takiego jak lokalna epoka! Nie jestem pewien, czy rozumiem twój problem.
Chetan Sastry
Może strefa czasowa na komputerze jest nieprawidłowa, co prowadzi do innej wartości UTC?
kijin
2
Musisz ustawić swój zegar na czas UTC, jeśli chcesz „zobaczyć” czas UTC, gdy używasz toLocaleString (). Północ UTC jest 19:00 EST. Jeśli użyjesz nowego Date (). ToString () zamiast localeString, otrzymasz coś takiego: „Pt 07 stycznia 2011 07:00:00 GMT-0500”, który zawiera przesunięcie.
kennebec

Odpowiedzi:

463

Myślę, że mam prostsze rozwiązanie - ustaw datę początkową epoki i dodaj jednostki UTC. Załóżmy, że masz zapisaną epokę var UTC w sekundach. Jak o 1234567890. Aby przekonwertować to na właściwą datę w lokalnej strefie czasowej:

var utcSeconds = 1234567890;
var d = new Date(0); // The 0 there is the key, which sets the date to the epoch
d.setUTCSeconds(utcSeconds);

d jest teraz ustawioną datą (w mojej strefie czasowej) Fri Feb 13 2009 18:31:30 GMT-0500 (EST)

użytkownik1030503
źródło
189
FWIW, Obiekty daty mogą być inicjowane w milisekundach. var d = new Date(utcSeconds * 1000)Powinien więc dać ten sam wynik.
kurttheviking,
54
var d = new Date(1234567890000)zwraca ten sam wynik
Matjaz Lipus
11
Pomyślałem, że może inni mogą uzyskać pewną przejrzystość z kilku punktów: obiekt daty nie jest ustawiany ze strefą czasową „wytłoczoną w nim”. myśl o tym jak o niczym innym jak o liczbie. liczba ta jest liczbą milisekund od 1970 do 1 stycznia UTC do chwili obecnej (teraz również w UTC). Tak więc, za każdym razem, gdy tworzysz obiekt daty, jest on naprawdę w UTC za kulisami. 2. Aby wyświetlić tę datę, możesz wyświetlić ją jako ustawienie regionalne (toLocaleString () lub, w UTC (toUTCString ()). Nie musisz niczego samodzielnie konwertować. Konstruuj za pomocą utc millisec, wszystko dobrze. Konstruuj za pomocą string - o ile znajduje się w lokalnej strefie czasowej
da Bich
2
1234567890000 jest traktowany tak samo jak 1234567890, znany również jako problem Y39K ...
baraninaUp
1
@muttonUp, przy 1000 mulitplication zadziałało. Ale Google „problem Y39K” nie daje żadnego poprawnego wyniku. Dowolny adres URL będzie pomocny
P Satish Patro
237

To proste, new Date()zajmuje tylko milisekundy, np

new Date(1394104654000)
> Thu Mar 06 2014 06:17:34 GMT-0500 (EST)
djechlin
źródło
6
Niezłe! To naprawdę należy uznać za przyjętą odpowiedź.
Nizar B.,
Ten nie działał dla mnie, działa, gdy masz znacznik czasu, ale w epoce utc musisz ustawić utcseconds ręcznie, odpowiedź jest prawidłowa
sameerali
12
To jest odpowiednia odpowiedź. Nowa data może podjąć milisekund, więc po prostu pomnożyć przez 1000: const d = new Date(epoch * 1000).
vinyll,
@sameerali Być może miałeś inny problem z systemem lub się zdezorientowałeś. Ta odpowiedź jest poprawna. Definicja epoki Uniksa: liczba sekund, które upłynęły od 1 stycznia o północy UTC . Wystarczy pomnożyć przez 1000, aby uzyskać liczbę upływających milisekund.
dokładnie
32

I tylko dla dzienników zrobiłem to przy użyciu biblioteki Moment.js , której i tak używałem do formatowania.

moment.utc(1234567890000).local()
>Fri Feb 13 2009 19:01:30 GMT-0430 (VET)
Gus
źródło
1
Moment jest przyjemny, ale szaleństwem jest użycie biblioteki 1,3 MB do konwersji jednej epoki na datę. Nic dziwnego, że istnieje tak wiele rozdętych aplikacji węzłów.
not2qubit
20

Czas epoki jest wyrażony w sekundach od 1 stycznia 1970 r. date.getTime()Zwraca milisekundy od 1 stycznia 1970 r., Więc .. jeśli masz znacznik czasu epoki, przekonwertuj go na znacznik czasu javascript, mnożąc przez 1000.

   function epochToJsDate(ts){
        // ts = epoch timestamp
        // returns date obj
        return new Date(ts*1000);
   }

   function jsDateToEpoch(d){
        // d = javascript date obj
        // returns epoch timestamp
        return (d.getTime()-d.getMilliseconds())/1000;
   }
logika 8
źródło
Zastanawiałem się, co u licha było. Bardzo dobrze wiedzieć, że epochTime! == javascriptTime, jeśli chodzi o parsowanie daty. Dzięki!
GrayedFox
16
 function ToLocalDate (inDate) {
    var date = new Date();
    date.setTime(inDate.valueOf() - 60000 * inDate.getTimezoneOffset());
    return date;
}
Chris
źródło
1
Zrobiłeś mi dzień. TY. Właśnie zastąpiłem znak minus znakiem plus dla mojej pracy.
Ludovic Kuty,
5

Aby przekonwertować bieżący czas epoki w [ms] na czas 24-godzinny. Może być konieczne określenie opcji wyłączenia formatu 12-godzinnego .

$ node.exe -e "var date = new Date(Date.now()); console.log(date.toLocaleString('en-GB', { hour12:false } ));"

2/7/2018, 19:35:24

lub jako JS:

var date = new Date(Date.now()); 
console.log(date.toLocaleString('en-GB', { hour12:false } ));
// 2/7/2018, 19:35:24

console.log(date.toLocaleString('en-GB', { hour:'numeric', minute:'numeric', second:'numeric', hour12:false } ));
// 19:35:24

Uwaga: użycie en-GBtutaj jest tylko (losowym) wyborem miejsca w formacie 24-godzinnym, nie jest to twoja strefa czasowa!

not2qubit
źródło
1
Jest to najlepszy sposób na uzyskanie dowolnego rodzaju konwersji z metody Date. Dzięki!
SeaWarrior404
Jedyne, co mi się nie podoba w powyższym, to to, że zwraca datę w tak dwuznacznym formacie, d/m/yyyyczy to jest m/d/yyyy? Prawo (najbardziej logiczny) sposób wyświetlania to powinno być: yyyy-mm-dd. Jacyś chętni?
not2qubit
4

Czas Epoki (tj. Czas Epoki Uniksa) jest prawie zawsze liczbą sekund , które upłynęły od 1 stycznia 1970 r. 00:00:00 (czasu UTC), a nie liczbą milisekund, które sugerują niektóre odpowiedzi tutaj.

https://en.wikipedia.org/wiki/Unix_time

Dlatego jeśli otrzymałeś wartość czasu Epoki Uniksowej, prawdopodobnie będzie to za kilka sekund i będzie wyglądało podobnie 1547035195. Jeśli chcesz, aby ten człowiek był czytelny w JavaScript, musisz przekonwertować wartość na milisekundy i przekazać tę wartość do Date(value)konstruktora, np .:

const unixEpochTimeMS = 1547035195 * 1000;
const d = new Date(unixEpochTimeMS);
// Careful, the string output here can vary by implementation...
const strDate = d.toLocaleString();

Nie musisz robić d.setUTCMilliseconds(0)kroku w zaakceptowanej odpowiedzi, ponieważ Date(value)konstruktor JavaScript przyjmuje wartość UTC w milisekundach (nie w czasie lokalnym).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#Syntax

Należy również pamiętać, że należy unikać używania Date(...)konstruktora, który przyjmuje ciąg reprezentujący datę i godzinę, nie jest to zalecane (patrz link powyżej).

garryp
źródło
3

Czy chcesz tylko przekonwertować ciąg UTC na ciąg „lokalny”? Mógłbyś:

var utc_string = '2011-09-05 20:05:15';
var local_string = (function(dtstr) {
    var t0 = new Date(dtstr);
    var t1 = Date.parse(t0.toUTCString().replace('GMT', ''));
    var t2 = (2 * t0) - t1;
    return new Date(t2).toString();
})(utc_string);
ZagNut
źródło
3

Dodatek do powyższej odpowiedzi @djechlin

d = '1394104654000';
new Date(parseInt(d));

konwertuje czas EPOCH na datę czytelną dla człowieka. Tylko nie zapomnij, że ten rodzaj czasu EPOCH musi być liczbą całkowitą.

Sarvar Nishonboev
źródło
3

Najprostszym rozwiązaniem, jakie znalazłem, jest:

var timestamp = Date.now(), // returns milliseconds since epoch time
    normalisedTime = new Date(timestamp);

Zauważ, że nie ma to * 1000na końcu new Date(timestamp)oświadczenia, ponieważ to (w każdym razie dla mnie!) Zawsze wydaje się podawać niewłaściwą datę, tj. Zamiast podawać rok 2019, podaje rok jako 51015, więc pamiętaj o tym.

Rob P.
źródło
2

Jeśli wolisz rozstrzygać konwersje znaczników czasu i dat z UTC i czasu lokalnego bez bibliotek takich jak moment.js, spójrz na opcję poniżej.

W przypadku aplikacji korzystających ze znaczników czasu UTC może być konieczne wyświetlenie daty w przeglądarce, biorąc pod uwagę lokalną strefę czasową i czas letni, jeśli dotyczy. Edycja daty, która ma inny czas letni, mimo że w tej samej strefie czasowej może być trudna.

Poniższe rozszerzenia Numberi Datepozwalają wyświetlać i uzyskiwać daty w strefie czasowej znaczników czasu. Załóżmy na przykład, że jesteś w Vancouver, jeśli edytujesz datę w lipcu lub w grudniu, może to oznaczać, że edytujesz datę w PST lub PDT.

Zalecam sprawdzenie fragmentu kodu poniżej, aby przetestować to rozwiązanie.

Konwersje z milisekund

Number.prototype.toLocalDate = function () {
    var value = new Date(this);

    value.setHours(value.getHours() + (value.getTimezoneOffset() / 60));

    return value;
};

Number.prototype.toUTCDate = function () {
    var value = new Date(this);

    value.setHours(value.getHours() - (value.getTimezoneOffset() / 60));

    return value;
};

Konwersje z dat

Date.prototype.getUTCTime = function () {
    return this.getTime() - (this.getTimezoneOffset() * 60000);
};

Stosowanie

// Adds the timezone and daylight savings if applicable
(1499670000000).toLocalDate();

// Eliminates the timezone and daylight savings if applicable
new Date(2017, 6, 10).getUTCTime();

Przekonaj się sam

Darlesson
źródło
To jest właściwa odpowiedź. Dla mnie zadziałało jak urok. Ustawienie nowej daty (0) i dodanie milliSeconds jest takie samo, jak nowa data (milliSeconds)
Jersey_Guy
1

EDYTOWAĆ

var utcDate = new Date(incomingUTCepoch);
var date = new Date();
date.setUTCDate(utcDate.getDate());
date.setUTCHours(utcDate.getHours());
date.setUTCMonth(utcDate.getMonth());
date.setUTCMinutes(utcDate.getMinutes());
date.setUTCSeconds(utcDate.getSeconds());
date.setUTCMilliseconds(utcDate.getMilliseconds());

EDYCJA naprawiona

Amjad Masad
źródło
Przeszedłem przez to w moim drugim przykładzie. Różnice, które mi daje, mieszczą się w przedziale od 50 do 900, co jest w milisekundach (pokazuje czas podczas przetwarzania obliczeń, a nie rzeczywistą różnicę)
Shane Reustle
Żadne z nich mi nie pomaga. Brakuje im metody setUTCTime, która byłaby idealna: P w3schools.com/jsref/jsref_obj_date.asp
Shane Reustle
Nie działa, przynajmniej w przeglądarce Firefox dla Ubuntu. Kod nie powinien ustawiać dnia / miesiąca / roku po ustawieniu daty.
Simon Kozlov,
@Simon Kozlov Właściwie to błędne założenie w obiekcie daty, setDate i getDate odnoszą się do dnia w miesiącu, a problem polega na tym, że użyłem funkcji takich jak (setUTCDay), które nie istnieją, zaskoczony, że został zaakceptowany !!
Amjad Masad
@AmjadMasad Twoja odpowiedź byłaby bardziej pomocna, jeśli pokażesz również oczekiwany wynik.
not2qubit
0

Biorąc pod uwagę, masz epoch_timedostępne,

// for eg. epoch_time = 1487086694.213
var date = new Date(epoch_time * 1000); // multiply by 1000 for milliseconds
var date_string = date.toLocaleString('en-GB');  // 24 hour format
apurva.nandan
źródło
0

@Amjad, dobry pomysł, ale lepszym rozwiązaniem byłoby:

Date.prototype.setUTCTime = function(UTCTimestamp) {
    var UTCDate = new Date(UTCTimestamp);
    this.setUTCFullYear(UTCDate.getFullYear(), UTCDate.getMonth(), UTCDate.getDate());
    this.setUTCHours(UTCDate.getHours(), UTCDate.getMinutes(), UTCDate.getSeconds(), UTCDate.getMilliseconds());
    return this.getTime();
}
Walf
źródło
-1

Najpierw przekonwertuj go na String, a następnie zamień tekst strefy czasowej.

function convertUnixTime(time) {
  return new Date(time*1000).toString().replace("GMT+0530 (Sri Lanka Standard Time)","");
}
Robot Boy
źródło