Utwórz datę z ustawioną strefą czasową bez użycia reprezentacji ciągu

412

Mam stronę internetową z trzema listami rozwijanymi dla dnia, miesiąca i roku. Jeśli użyję Datekonstruktora JavaScript, który pobiera liczby, to otrzymam Dateobiekt dla mojej bieżącej strefy czasowej:

new Date(xiYear, xiMonth, xiDate)

Podaj poprawną datę, ale wydaje się, że data ta to GMT + 01: 00 ze względu na czas letni.

Problem polega na tym, że następnie przekazuję to Datedo metody Ajax, a kiedy data na serwerze jest przekształcana w postaci szeregowej, jest konwertowana na GMT i tak traci godzinę, która przesuwa dzień wstecz o jedną. Teraz mógłbym tylko przekazać dzień, miesiąc i rok indywidualnie do metody Ajax, ale wydaje się, że powinien istnieć lepszy sposób.

Przyjęta odpowiedź wskazała mi właściwy kierunek, jednak setUTCHours()zmieniło się samo użycie :

Apr 5th 00:00 GMT+01:00 

do

Apr 4th 23:00 GMT+01:00

Następnie musiałem ustawić datę UTC, miesiąc i rok

Apr 5th 01:00 GMT+01:00

co chciałem.

Dan
źródło
9
Gdyby zaakceptowana odpowiedź wskazywała właściwy kierunek, ale nie odpowiedziała na twoje pytanie, argumentowałbym, że nie powinna to być odpowiedź zaakceptowana. Odpowiedź powinna odpowiedzieć na zadane pytanie.
TWR Cole

Odpowiedzi:

481

korzystanie z .setUTCHours()niego byłoby możliwe, aby faktycznie ustawić daty w czasie UTC, co pozwoliłoby na użycie czasów UTC w całym systemie.

Nie możesz jednak ustawić go za pomocą UTC w konstruktorze, chyba że podasz ciąg daty.

Za pomocą new Date(Date.UTC(year, month, day, hour, minute, second))możesz utworzyć obiekt daty z określonego czasu UTC.

jishi
źródło
101
Składnia „new Date (Date.UTC (...))” pozwala utworzyć datę, która jest równoważna z datą UTC pod względem czasu, który reprezentuje, ale nie jest taka sama - ma inna strefa czasowa (inna niż UTC).
Anthony
52
Należy pamiętać, że przy użyciu „Data” wartość „miesiąc” ma zakres od 0 do 11 (nie od 1 do 12). Ciągle otrzymywałem przesunięcie strefy czasowej o 2 godziny (chociaż powinno to być 1 godzinę) i zajęło mi godziny, aby dowiedzieć się, że przyczyną był zły miesiąc.
Wybierz 0
4
Ta odpowiedź jest świetna. Ale używam biblioteki [datepicker ui], która używa nowej daty w wielu miejscach. Chcę tylko ustawić strefę czasową UTC, a każda data jest zgodna z nową strefą czasową. Dziwi mnie, że Javascript nie ma na to nic.
Sanjeev Kumar Dangi
6
@ jishi - obiekty daty są oparte na wartości czasu UTC, a nie czasu lokalnego. Jednak domyślna metoda Date.prototype.toString wyświetli wartości czasu lokalnego.
RobG
5
@ Anthony - „ ale to nie ten sam czas ” jest niepoprawny. Reprezentuje dokładnie ten sam moment w czasie, jedyną różnicą jest przesunięcie strefy czasowej.
RobG
198
var d = new Date(xiYear, xiMonth, xiDate);
d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );

Ta odpowiedź jest specjalnie dostosowana do pierwotnego pytania i nie daje odpowiedzi, której koniecznie oczekujesz. W szczególności niektóre osoby będą chciały odjąć przesunięcie strefy czasowej zamiast go dodać. Pamiętaj jednak, że sedno tego rozwiązania polega na zhakowaniu obiektu daty javascript dla określonej deserializacji, a nie we wszystkich przypadkach.

TWR Cole
źródło
62
@ gthmb oczywiście, ale wydaje mi się, że *60*1000w tym przypadku jest to jaśniejsze; innymi słowy, jest dość oczywiste, dlaczego tam jest.
TWR Cole
22
To prawie działa dla mnie, tyle że muszę użyć - (minus) zamiast + (plus), aby uzyskać właściwy czas dla mojej strefy czasowej.
Wytze
3
Tak, jak zauważyli inni - myślę, że w tej odpowiedzi jest błąd. Powinno być minus nie plus.
UpTheCreek
3
Zgodnie z developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… wartość zwracana przez getTimezoneOffset jest podpisywana zgodnie z rzeczywistym przesunięciem w ustawieniach regionalnych w momencie wywołania funkcji, w tym z uwzględnieniem czasu letniego, więc nie rozumiem, dlaczego trzeba to odjąć.
TWR Cole,
15
Jeśli dodasz timezoneOffset do obiektu daty, jego wartość sformatowana w lokalnej strefie czasowej będzie wyglądać jak poprawna wartość w UTC, ale nadal będzie miała oryginalne przesunięcie strefy czasowej (a niektóre reprezentacje, takie jak „ISOString”, faktycznie ją pokażą). Tak więc w zależności od sposobu następnie serializacji obiektu data, JS może zastosować przesunięcie strefy czasowej ponownie , co daje złą odpowiedź. Uważam, że jest to odpowiedzialne za zamieszanie w tych komentarzach między +/-. W każdym razie moje zdanie jest za tym faktem, a także za „w większości przypadków dostajesz to, czego oczekujesz”.
metamatt
173

Wierzę, że potrzebujemy createDateAsUTC funkcji (proszę porównać z convertDateToUTC )

function createDateAsUTC(date) {
    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));
}

function convertDateToUTC(date) { 
    return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); 
}
monsterclub
źródło
36
Dziwi mnie jego jasność i pomoc w udzielaniu odpowiedzi. Nie wiedziałem, że praca z datami Javascript była takim koszmarem do dziś: S
will824
Chcesz wyjaśnić różnicę między nimi? Pierwszy przekształca się datew strefę czasową UTC, ale drugi wydaje się nie robić nic przydatnego? (zwraca tę samą datę jak date)
Jonathan Lin
4
Rozumiem teraz: pierwsza zwraca datę w strefie czasowej UTC, z dosłownymi wartościami daty czasu lokalnego. Drugi zwraca datę w lokalnej strefie czasowej, ale z literalnymi wartościami daty UTC.
Jonathan Lin
8
To podejście jest jedną implementacją wzorca zwanego „przesunięciem epoki”, który ma na celu przesunięcie epoki (opartej na UTC) na taki, który jest przesunięty o bieżące przesunięcie strefy czasowej. Niestety, chociaż jest to powszechnie widoczne, takie podejście jest wadliwe. DateObiekt JavaScript zawsze będzie odzwierciedlał epokę uniksową opartą na UTC i lokalną strefę czasową. Objaw jest widoczny, gdy wywołujesz toStringwynikowy obiekt daty i nadal widzisz lokalną strefę czasową, nawet jeśli spodziewałeś się, że jest to UTC.
Matt Johnson-Pint
2
Może także powodować błędy w wartościach czasowych, w pobliżu przejściowych zmian czasu lokalnego w strefie czasu letniego. Krótko mówiąc, przesunięcie epoki (za pośrednictwem dowolnej implementacji) nie działa z Dateobiektem JavaScript . Innym sposobem, aby zobaczyć to tutaj, jest Date.UTCoczekiwanie wartości opartych na UTC, a Ty podajesz wartości czasu lokalnego i odwrotnie za pomocą Datekonstruktora.
Matt Johnson-Pint
70

Wystarczy ustawić strefę czasową i wrócić zgodnie

new Date().toLocaleString("en-US", {timeZone: "America/New_York"})

Inne strefy czasowe są następujące

var world_timezones =
[
    'Europe/Andorra',
    'Asia/Dubai',
    'Asia/Kabul',
    'Europe/Tirane',
    'Asia/Yerevan',
    'Antarctica/Casey',
    'Antarctica/Davis',
    'Antarctica/DumontDUrville', 
    'Antarctica/Mawson',
    'Antarctica/Palmer',
    'Antarctica/Rothera',
    'Antarctica/Syowa',
    'Antarctica/Troll',
    'Antarctica/Vostok',
    'America/Argentina/Buenos_Aires',
    'America/Argentina/Cordoba',
    'America/Argentina/Salta',
    'America/Argentina/Jujuy',
    'America/Argentina/Tucuman',
    'America/Argentina/Catamarca',
    'America/Argentina/La_Rioja',
    'America/Argentina/San_Juan',
    'America/Argentina/Mendoza',
    'America/Argentina/San_Luis',
    'America/Argentina/Rio_Gallegos',
    'America/Argentina/Ushuaia',
    'Pacific/Pago_Pago',
    'Europe/Vienna',
    'Australia/Lord_Howe',
    'Antarctica/Macquarie',
    'Australia/Hobart',
    'Australia/Currie',
    'Australia/Melbourne',
    'Australia/Sydney',
    'Australia/Broken_Hill',
    'Australia/Brisbane',
    'Australia/Lindeman',
    'Australia/Adelaide',
    'Australia/Darwin',
    'Australia/Perth',
    'Australia/Eucla',
    'Asia/Baku',
    'America/Barbados',
    'Asia/Dhaka',
    'Europe/Brussels',
    'Europe/Sofia',
    'Atlantic/Bermuda',
    'Asia/Brunei',
    'America/La_Paz',
    'America/Noronha',
    'America/Belem',
    'America/Fortaleza',
    'America/Recife',
    'America/Araguaina',
    'America/Maceio',
    'America/Bahia',
    'America/Sao_Paulo',
    'America/Campo_Grande',
    'America/Cuiaba',
    'America/Santarem',
    'America/Porto_Velho',
    'America/Boa_Vista',
    'America/Manaus',
    'America/Eirunepe',
    'America/Rio_Branco',
    'America/Nassau',
    'Asia/Thimphu',
    'Europe/Minsk',
    'America/Belize',
    'America/St_Johns',
    'America/Halifax',
    'America/Glace_Bay',
    'America/Moncton',
    'America/Goose_Bay',
    'America/Blanc-Sablon',
    'America/Toronto',
    'America/Nipigon',
    'America/Thunder_Bay',
    'America/Iqaluit',
    'America/Pangnirtung',
    'America/Atikokan',
    'America/Winnipeg',
    'America/Rainy_River',
    'America/Resolute',
    'America/Rankin_Inlet',
    'America/Regina',
    'America/Swift_Current',
    'America/Edmonton',
    'America/Cambridge_Bay',
    'America/Yellowknife',
    'America/Inuvik',
    'America/Creston',
    'America/Dawson_Creek',
    'America/Fort_Nelson',
    'America/Vancouver',
    'America/Whitehorse',
    'America/Dawson',
    'Indian/Cocos',
    'Europe/Zurich',
    'Africa/Abidjan',
    'Pacific/Rarotonga',
    'America/Santiago',
    'America/Punta_Arenas',
    'Pacific/Easter',
    'Asia/Shanghai',
    'Asia/Urumqi',
    'America/Bogota',
    'America/Costa_Rica',
    'America/Havana',
    'Atlantic/Cape_Verde',
    'America/Curacao',
    'Indian/Christmas',
    'Asia/Nicosia',
    'Asia/Famagusta',
    'Europe/Prague',
    'Europe/Berlin',
    'Europe/Copenhagen',
    'America/Santo_Domingo',
    'Africa/Algiers',
    'America/Guayaquil',
    'Pacific/Galapagos',
    'Europe/Tallinn',
    'Africa/Cairo',
    'Africa/El_Aaiun',
    'Europe/Madrid',
    'Africa/Ceuta',
    'Atlantic/Canary',
    'Europe/Helsinki',
    'Pacific/Fiji',
    'Atlantic/Stanley',
    'Pacific/Chuuk',
    'Pacific/Pohnpei',
    'Pacific/Kosrae',
    'Atlantic/Faroe',
    'Europe/Paris',
    'Europe/London',
    'Asia/Tbilisi',
    'America/Cayenne',
    'Africa/Accra',
    'Europe/Gibraltar',
    'America/Godthab',
    'America/Danmarkshavn',
    'America/Scoresbysund',
    'America/Thule',
    'Europe/Athens',
    'Atlantic/South_Georgia',
    'America/Guatemala',
    'Pacific/Guam',
    'Africa/Bissau',
    'America/Guyana',
    'Asia/Hong_Kong',
    'America/Tegucigalpa',
    'America/Port-au-Prince',
    'Europe/Budapest',
    'Asia/Jakarta',
    'Asia/Pontianak',
    'Asia/Makassar',
    'Asia/Jayapura',
    'Europe/Dublin',
    'Asia/Jerusalem',
    'Asia/Kolkata',
    'Indian/Chagos',
    'Asia/Baghdad',
    'Asia/Tehran',
    'Atlantic/Reykjavik',
    'Europe/Rome',
    'America/Jamaica',
    'Asia/Amman',
    'Asia/Tokyo',
    'Africa/Nairobi',
    'Asia/Bishkek',
    'Pacific/Tarawa',
    'Pacific/Enderbury',
    'Pacific/Kiritimati',
    'Asia/Pyongyang',
    'Asia/Seoul',
    'Asia/Almaty',
    'Asia/Qyzylorda',
    'Asia/Qostanay', 
    'Asia/Aqtobe',
    'Asia/Aqtau',
    'Asia/Atyrau',
    'Asia/Oral',
    'Asia/Beirut',
    'Asia/Colombo',
    'Africa/Monrovia',
    'Europe/Vilnius',
    'Europe/Luxembourg',
    'Europe/Riga',
    'Africa/Tripoli',
    'Africa/Casablanca',
    'Europe/Monaco',
    'Europe/Chisinau',
    'Pacific/Majuro',
    'Pacific/Kwajalein',
    'Asia/Yangon',
    'Asia/Ulaanbaatar',
    'Asia/Hovd',
    'Asia/Choibalsan',
    'Asia/Macau',
    'America/Martinique',
    'Europe/Malta',
    'Indian/Mauritius',
    'Indian/Maldives',
    'America/Mexico_City',
    'America/Cancun',
    'America/Merida',
    'America/Monterrey',
    'America/Matamoros',
    'America/Mazatlan',
    'America/Chihuahua',
    'America/Ojinaga',
    'America/Hermosillo',
    'America/Tijuana',
    'America/Bahia_Banderas',
    'Asia/Kuala_Lumpur',
    'Asia/Kuching',
    'Africa/Maputo',
    'Africa/Windhoek',
    'Pacific/Noumea',
    'Pacific/Norfolk',
    'Africa/Lagos',
    'America/Managua',
    'Europe/Amsterdam',
    'Europe/Oslo',
    'Asia/Kathmandu',
    'Pacific/Nauru',
    'Pacific/Niue',
    'Pacific/Auckland',
    'Pacific/Chatham',
    'America/Panama',
    'America/Lima',
    'Pacific/Tahiti',
    'Pacific/Marquesas',
    'Pacific/Gambier',
    'Pacific/Port_Moresby',
    'Pacific/Bougainville',
    'Asia/Manila',
    'Asia/Karachi',
    'Europe/Warsaw',
    'America/Miquelon',
    'Pacific/Pitcairn',
    'America/Puerto_Rico',
    'Asia/Gaza',
    'Asia/Hebron',
    'Europe/Lisbon',
    'Atlantic/Madeira',
    'Atlantic/Azores',
    'Pacific/Palau',
    'America/Asuncion',
    'Asia/Qatar',
    'Indian/Reunion',
    'Europe/Bucharest',
    'Europe/Belgrade',
    'Europe/Kaliningrad',
    'Europe/Moscow',
    'Europe/Simferopol',
    'Europe/Kirov',
    'Europe/Astrakhan',
    'Europe/Volgograd',
    'Europe/Saratov',
    'Europe/Ulyanovsk',
    'Europe/Samara',
    'Asia/Yekaterinburg',
    'Asia/Omsk',
    'Asia/Novosibirsk',
    'Asia/Barnaul',
    'Asia/Tomsk',
    'Asia/Novokuznetsk',
    'Asia/Krasnoyarsk',
    'Asia/Irkutsk',
    'Asia/Chita',
    'Asia/Yakutsk',
    'Asia/Khandyga',
    'Asia/Vladivostok',
    'Asia/Ust-Nera',
    'Asia/Magadan',
    'Asia/Sakhalin',
    'Asia/Srednekolymsk',
    'Asia/Kamchatka',
    'Asia/Anadyr',
    'Asia/Riyadh',
    'Pacific/Guadalcanal',
    'Indian/Mahe',
    'Africa/Khartoum',
    'Europe/Stockholm',
    'Asia/Singapore',
    'America/Paramaribo',
    'Africa/Juba',
    'Africa/Sao_Tome',
    'America/El_Salvador',
    'Asia/Damascus',
    'America/Grand_Turk',
    'Africa/Ndjamena',
    'Indian/Kerguelen',
    'Asia/Bangkok',
    'Asia/Dushanbe',
    'Pacific/Fakaofo',
    'Asia/Dili',
    'Asia/Ashgabat',
    'Africa/Tunis',
    'Pacific/Tongatapu',
    'Europe/Istanbul',
    'America/Port_of_Spain',
    'Pacific/Funafuti',
    'Asia/Taipei',
    'Europe/Kiev',
    'Europe/Uzhgorod',
    'Europe/Zaporozhye',
    'Pacific/Wake',
    'America/New_York',
    'America/Detroit',
    'America/Kentucky/Louisville',
    'America/Kentucky/Monticello',
    'America/Indiana/Indianapolis',
    'America/Indiana/Vincennes',
    'America/Indiana/Winamac',
    'America/Indiana/Marengo',
    'America/Indiana/Petersburg',
    'America/Indiana/Vevay',
    'America/Chicago',
    'America/Indiana/Tell_City',
    'America/Indiana/Knox',
    'America/Menominee',
    'America/North_Dakota/Center',
    'America/North_Dakota/New_Salem',
    'America/North_Dakota/Beulah',
    'America/Denver',
    'America/Boise',
    'America/Phoenix',
    'America/Los_Angeles',
    'America/Anchorage',
    'America/Juneau',
    'America/Sitka',
    'America/Metlakatla',
    'America/Yakutat',
    'America/Nome',
    'America/Adak',
    'Pacific/Honolulu',
    'America/Montevideo',
    'Asia/Samarkand',
    'Asia/Tashkent',
    'America/Caracas',
    'Asia/Ho_Chi_Minh',
    'Pacific/Efate',
    'Pacific/Wallis',
    'Pacific/Apia',
    'Africa/Johannesburg'
];
Matee Gojra
źródło
8
To powinno być na górze
Eugene
Trzeba jednak pamiętać, że nie działa to w niektórych przeglądarkach. Na przykład. IE11.
Paul LeBeau,
Błąd w konsoli IE: Wartość opcji „AMERICA / NEW_YORK” dla „timeZone” jest poza prawidłowym zakresem. Oczekiwany: [„UTC”] @OloghoCyrilPaul
Matee Gojra,
1
Bardzo łatwe, bardzo eleganckie. Możesz znaleźć tutaj listę wszystkich stref czasowych stackoverflow.com/questions/38399465/… . W przypadku UTC wybierz strefę czasową Londynu.
EPurpl3,
1
Żadna z tych wartości nie jest „strefami czasowymi”, są to lokalizacje reprezentatywne dla bazy danych stref czasowych IANA dla miejsc, które mają tę samą historyczną lokalną strefę czasową i zmiany czasu letniego.
RobG,
28

Nie sądzę, aby było to możliwe - po utworzeniu nie ma możliwości ustawienia strefy czasowej dla obiektu Date.

I w pewnym sensie ma to sens - koncepcyjnie (jeśli nie we wdrażaniu); na http://en.wikipedia.org/wiki/Unix_timestamp (moje podkreślenie):

Czas uniksowy lub czas POSIX to system do opisywania chwil w czasie, zdefiniowany jako liczba sekund, które upłynęły od północy skoordynowanego czasu uniwersalnego (UTC) w czwartek, 1 stycznia 1970 r.

Kiedy go zbudujesz, będzie on reprezentował pewien punkt w „czasie rzeczywistym”. Strefa czasowa ma znaczenie tylko wtedy, gdy chcesz przekonwertować ten abstrakcyjny punkt czasowy na ciąg czytelny dla człowieka.

Dlatego sensowne jest, że możesz zmienić rzeczywisty czas, jaki Data reprezentuje w konstruktorze. Niestety wydaje się, że nie ma możliwości przejścia w wyraźnej strefie czasowej - a wywoływany przez ciebie konstruktor (prawdopodobnie poprawny) tłumaczy twoje „lokalne” zmienne czasowe na GMT, gdy przechowuje je kanonicznie - więc nie ma możliwości użycia int, int, intkonstruktora do Czasy GMT.

Plusem jest to, że użycie konstruktora, który pobiera ciąg znaków, jest banalne. Nie musisz nawet konwertować miesiąca liczbowego na ciąg znaków (przynajmniej w przeglądarce Firefox), więc miałem nadzieję, że naiwna implementacja zadziała. Jednak po wypróbowaniu działa z powodzeniem w Firefox, Chrome i Opera, ale kończy się niepowodzeniem w Konquerorze („Nieprawidłowa data”), Safari („Nieprawidłowa data”) i IE („NaN”). Przypuszczam, że masz po prostu tablicę odnośników do konwersji miesiąca na ciąg znaków, na przykład:

var months = [ '', 'January', 'February', ..., 'December'];

function createGMTDate(xiYear, xiMonth, xiDate) {
   return new Date(months[xiMonth] + ' ' + xiDate + ', ' + xiYear + ' 00:00:00 GMT');
}
Andrzej Doyle
źródło
6
Jeśli nie ma sposobu, aby „ustawić strefę czasową na obiekcie Date po jej utworzeniu”, czy sugerujesz, że istnieje sposób na ustawienie strefy czasowej na obiekt Date podczas jego tworzenia? Nie wygląda na to, żeby data js była „cienkim opakowaniem w ciągu kilku sekund od Epoki” - wygląda na to, że liczy się liczba sekund plus strefa czasowa.
Anthony
1
@Anthony, może używać tylko strefy czasowej klienta. JavaScript może wykonywać operacje lokalne na utc iz powrotem, ale nie ma dostępu do bazy danych stref czasowych. Nie może na przykład podać godziny w Meksyku, gdy jesteś w San Diego.
Samuel Danielson
20

Wiem, że to stare, ale jeśli to pomoże, możesz użyć strefy czasowej chwili i chwili. Jeśli ich nie widziałeś, spójrz.

http://momentjs.com/timezone/

http://momentjs.com/

dwie naprawdę przydatne biblioteki manipulacji czasem.

ChewOnThis_Trident
źródło
16

Jeśli chcesz poradzić sobie z nieco innym, ale pokrewnym, problemem tworzenia obiektu JavaScript Data z roku, miesiąca, dnia, ..., w tym strefy czasowej - to znaczy, jeśli chcesz parsować ciąg znaków na datę - to najwyraźniej muszą wykonać irytująco skomplikowany taniec:

// parseISO8601String : string -> Date
// Parse an ISO-8601 date, including possible timezone,
// into a Javascript Date object.
//
// Test strings: parseISO8601String(x).toISOString()
// "2013-01-31T12:34"              -> "2013-01-31T12:34:00.000Z"
// "2013-01-31T12:34:56"           -> "2013-01-31T12:34:56.000Z"
// "2013-01-31T12:34:56.78"        -> "2013-01-31T12:34:56.780Z"
// "2013-01-31T12:34:56.78+0100"   -> "2013-01-31T11:34:56.780Z"
// "2013-01-31T12:34:56.78+0530"   -> "2013-01-31T07:04:56.780Z"
// "2013-01-31T12:34:56.78-0330"   -> "2013-01-31T16:04:56.780Z"
// "2013-01-31T12:34:56-0330"      -> "2013-01-31T16:04:56.000Z"
// "2013-01-31T12:34:56Z"          -> "2013-01-31T12:34:56.000Z"
function parseISO8601String(dateString) {
    var timebits = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})(?::([0-9]*)(\.[0-9]*)?)?(?:([+-])([0-9]{2})([0-9]{2}))?/;
    var m = timebits.exec(dateString);
    var resultDate;
    if (m) {
        var utcdate = Date.UTC(parseInt(m[1]),
                               parseInt(m[2])-1, // months are zero-offset (!)
                               parseInt(m[3]),
                               parseInt(m[4]), parseInt(m[5]), // hh:mm
                               (m[6] && parseInt(m[6]) || 0),  // optional seconds
                               (m[7] && parseFloat(m[7])*1000) || 0); // optional fraction
        // utcdate is milliseconds since the epoch
        if (m[9] && m[10]) {
            var offsetMinutes = parseInt(m[9]) * 60 + parseInt(m[10]);
            utcdate += (m[8] === '+' ? -1 : +1) * offsetMinutes * 60000;
        }
        resultDate = new Date(utcdate);
    } else {
        resultDate = null;
    }
    return resultDate;
}

Oznacza to, że utworzysz „czas UTC”, używając daty bez strefy czasowej (więc wiesz, w jakich ustawieniach regionalnych jest UTC, a mianowicie „ustawienia regionalne UTC” i nie są one domyślnie ustawione na lokalne), a następnie ręcznie zastosujesz wskazane przesunięcie strefy czasowej.

Czy nie byłoby miło, gdyby ktoś myślał o obiekcie z datą JavaScript dłużej niż, oooh, pięć minut ...

Norman Gray
źródło
1
dzięki za świetną funkcję! jedyne, co chciałbym zmienić, to dodać obsługę dwukropka w przesunięciu strefy czasowej. var timebits = / ^ ([0-9] {4}) - ([0-9] {2}) - ([0-9] {2}) T ([0-9] {2}) :( [0-9] {2}) (? :: ([0-9] *) (\. [0-9] *)?)? (?: ([+ -]) ([0-9] { 2} [:]?) ([0-9] {2}))? /;
robnardo,
2
Myśleli o tym; niestety „oni” byli projektantami języka Java, ponieważ JS właśnie skopiował klasę Date Java w celu jej początkowej implementacji.
Xanthir,
@Xanthir Oooh, masz rację, a ja zapomniałem, jak okropny był oryginalny obiekt Java Date; ale przynajmniej Java przestała go używać i ruszyła dalej, coś JavaScript wydaje się nie być w stanie zrobić (jest to dziwny język, JavaScript: raczej uroczy i nie tak okropny, jak się początkowo wydaje).
Norman Gray,
13
d = new Date();
utc = d.getTime() + (d.getTimezoneOffset() * 60000);
nd = new Date(utc + (3600000*offset));

offset value base on which location time zone you would like to set 
For India offset value +5.5,
New York offset value -4,
London offset value +1

dla wszystkich przesunięć lokalizacji Lista Wiki przesunięć czasowych UTC

Vijay Lathiya
źródło
Jak to pomaga dla Nowego Jorku w czasie letnim?
frederj
W przypadku Nowego Jorku należy użyć wartości przesunięcia -4
Vijay Lathiya
1
Przesunięcie dla Nowego Jorku różni się w zależności od czasu letniego. Czasami jest to -4, a czasem -5 en.wikipedia.org/wiki/Eastern_Time_Zone
frederj
8

getTimeZoneOffset ma wartość ujemną dla UTC + z.

var d = new Date(xiYear, xiMonth, xiDate);
if(d.getTimezoneOffset() > 0){
    d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );
}
rinjan
źródło
1
Mały błąd
,!
8

Może to komuś pomóc, umieścić UTC na końcu tego, co przekazujesz nowemu konstruktorowi

Przynajmniej w chromie można powiedzieć var date = new Date("2014-01-01 11:00:00 UTC")

Drew LeSueur
źródło
1
Zwraca „Niepoprawną datę” w Safari
pmrotule
1
Zamień `UTC` na +0000(zauważyłem, że spacja między 00 a UTC musi zostać usunięta), a to zadziała zarówno w przeglądarce Firefox, jak i Chrome. Nie jestem pewien co do Safari (odniesienie: stackoverflow.com/a/17545854/1273587 )
cytsunny
8

Rozwiązanie jednoliniowe

new Date(new Date(1422524805305).getTime() - 330*60*1000)

Zamiast 1422524805305 użyj znacznika czasu w milisekundach Zamiast 330, użyj przesunięcia strefy czasowej w minutach wrt. GMT (np. Indie +5: 30 to 5 * 60 + 30 = 330 minut)

Vinay Vemula
źródło
4
Byłby to kod uruchamiany na kliencie, co oznacza, że ​​strefa czasowa będzie inna dla różnych użytkowników. To rozwiązanie wymagałoby, aby wszyscy, którzy go potrzebują, żyli w tej samej strefie czasowej (twojej).
Kevin Beal
@Kevin Beal w takim przypadku wystarczy użyć getTimezoneOffset
maximus
6
// My clock 2018-07-25, 00:26:00 (GMT+7)
let date = new Date(); // 2018-07-24:17:26:00 (Look like GMT+0)
const myTimeZone = 7; // my timeZone 
// my timeZone = 7h = 7 * 60 * 60 * 1000 (millisecond);
// 2018-07-24:17:26:00 = x (milliseconds)
// finally, time in milliseconds (GMT+7) = x + myTimezone 
date.setTime( date.getTime() + myTimeZone * 60 * 60 * 1000 );
// date.toISOString() = 2018-07-25, 00:26:00 (GMT+7)
Tuan Nguyen
źródło
Wyjaśnienie kodu i sposób rozwiązania problemu podniesie jakość twojej odpowiedzi i pomoże w nauce użytkowników.
Nic3500,
5

Najłatwiejszym sposobem na znalezienie prawidłowej daty jest użycie datejs.

http://www.datejs.com/

Dostaję daty przez Ajax w tym formacie jako ciąg: „2016-01-12T00: 00: 00”

var yourDateString = '2016-01-12T00:00:00';
var yourDate = new Date(yourDateString);
console.log(yourDate);
if (yourDate.getTimezoneOffset() > 0){
    yourDate = new Date(yourDateString).addMinutes(yourDate.getTimezoneOffset());
}
console.log(yourDate);

Konsola będzie czytać:

Pn 11 stycznia 2016 19:00:00 GMT-0500 (wschodni czas standardowy)

Wt 12 stycznia 2016 00:00:00 GMT-0500 (wschodni czas standardowy)

https://jsfiddle.net/vp1ena7b/3/

„AddMinutes” pochodzi od datejs, prawdopodobnie mógłbyś to zrobić w czystym js na własną rękę, ale miałem już datejs w moim projekcie, więc znalazłem sposób, aby użyć go, aby uzyskać prawidłowe daty.

Myślałem, że to może komuś pomóc ...

Barry Franklin
źródło
Wypróbowałem wszystkie metody i to był jedyny sposób na zdobycie północy, o to mi chodziło!
SharpC
3

dowolny przebieg w

var d = new Date(xiYear, xiMonth, xiDate).toLocaleString();
miau
źródło
Wydaje mi się, że to załatwia sprawę (jedna strefa czasowa poza GMT), ale ponieważ „ustawienia regionalne” niekoniecznie są związane ze strefą czasową, nie polegałbym na tym.
Wytze
3

Ten kod zwróci obiekt Date sformatowany w strefie czasowej przeglądarki .

Date.prototype.timezone = function () {
    this.setHours(this.getHours() + (new Date().getTimezoneOffset() / 60));
    return this;
}

Edytować:

Aby uniknąć zanieczyszczenia interfejsu Data API, powyższą funkcję można przekształcić w funkcję narzędzia. Funkcja pobiera obiekt Date i zwraca zmutowany obiekt Date.

function setTimeZone(date) {
    date.setHours(date.getHours() + (new Date().getTimezoneOffset() / 60));
    return date;
}
Marco Dal Zovo
źródło
6
Nie dla rozszerzania rodzimych obiektów
Paul Rumkin
1

Najlepsze rozwiązanie, jakie widziałem z tego, pochodzi

http://www.codingforums.com/archive/index.php/t-19663.html

Funkcja czasu drukowania

<script language="javascript" type="text/javascript">
//borrowed from echoecho
//http://www.echoecho.com/ubb/viewthread.php?tid=2362&pid=10482&#pid10482
workDate = new Date()
UTCDate = new Date()
UTCDate.setTime(workDate.getTime()+workDate.getTimezoneOffset()*60000)

function printTime(offset) {
    offset++;
    tempDate = new Date()
    tempDate.setTime(UTCDate.getTime()+3600000*(offset))
    timeValue = ((tempDate.getHours()<10) ? ("0"+tempDate.getHours()) : (""+tempDate.getHours()))
    timeValue += ((tempDate.getMinutes()<10) ? ("0"+tempDate.getMinutes()) : tempDate.getMinutes())
    timeValue += " hrs."
    return timeValue
    }
    var now = new Date()
    var seed = now.getTime() % 0xfffffff
    var same = rand(12)
</script>

Banff, Canada:
<script language="JavaScript">document.write(printTime("-7"))</script>

Przykład pełnego kodu

<html>

<head>
<script language="javascript" type="text/javascript">
//borrowed from echoecho
//http://www.echoecho.com/ubb/viewthread.php?tid=2362&pid=10482&#pid10482
workDate = new Date()
UTCDate = new Date()
UTCDate.setTime(workDate.getTime()+workDate.getTimezoneOffset()*60000)

function printTime(offset) {
offset++;
tempDate = new Date()
tempDate.setTime(UTCDate.getTime()+3600000*(offset))
timeValue = ((tempDate.getHours()<10) ? ("0"+tempDate.getHours()) : (""+tempDate.getHours()))
timeValue += ((tempDate.getMinutes()<10) ? ("0"+tempDate.getMinutes()) : tempDate.getMinutes())
timeValue += " hrs."
return timeValue
}
var now = new Date()
var seed = now.getTime() % 0xfffffff
var same = rand(12)
</script>

</head>

<body>
Banff, Canada:
<script language="JavaScript">document.write(printTime("-7"))</script>
<br>
Michigan:
<script language="JavaScript">document.write(printTime("-5"))</script>
<br>
Greenwich, England(UTC):
<script language="JavaScript">document.write(printTime("-0"))</script>
<br>
Tokyo, Japan:
<script language="JavaScript">document.write(printTime("+9"))</script>
<br>
Berlin, Germany:
<script language="JavaScript">document.write(printTime("+1"))</script>

</body>
</html>
Jeffrey L. Roberts
źródło
Twój przykład wyklucza czas letni. CurrentTime: Pt 04 października 2013 11:13:43 GMT-0700 (Pacific Daylight Time) UtcTime: Pt, 04 października 2013 18:13:43 GMT Banff, Kanada: 1213 godz. Michigan: 1413 godz. Greenwich, England (UTC): 1913 godz. Tokio, Japonia: 0413 godz. Berlin, Niemcy: 2013 godz.
Jeson Martajaya
0

jeśli chcesz sprawdzić różnicę w czasie między dwiema datami, możesz po prostu sprawdzić, czy druga strefa czasowa jest mniejsza lub większa od pierwszej pożądanej strefy czasowej i odjąć lub dodać godzinę.

  const currTimezone = new Date().getTimezoneOffset(); // your timezone
  const newDateTimezone = date.getTimezoneOffset(); // date with unknown timezone

  if (currTimezone !== newDateTimezone) {
    // and below you are checking if difference should be - or +. It depends on if unknown timezone is lesser or greater than yours
    const newTimezone = (currTimezone - newDateTimezone) * (currTimezone > newDateTimezone ? 1 : -1);
    date.setTime(date.getTime() + (newTimezone * 60 * 1000));
  }
Piosek
źródło
0

GMT -03: 00 Przykład

new Date(new Date()-3600*1000*3).toISOString();  // 2020-02-27T15:03:26.261Z

Lub nawet

now  = new Date().getTime()-3600*1000*3; // 1582818380528
data = new Date(now).toISOString();      // 2020-02-27T15:03:26.261Z
Rafael Xavier
źródło
-1

To zadziałało dla mnie. Nie jestem jednak pewien, czy to dobry pomysł.

var myDate = new Date();
console.log('myDate:', myDate);   // myDate: "2018-04-04T01:09:38.112Z"

var offset = '+5';  // e.g. if the timeZone is -5

var MyDateWithOffset = new Date( myDate.toGMTString() + offset );   

console.log('MyDateWithOffset:', MyDateWithOffset); // myDateWithOffset: "2018-04-03T20:09:38.000Z"

ofmoreno06
źródło
-1

Użyłem pakietu timezone-js.

var timezoneJS  = require('timezone-js');
var tzdata = require('tzdata');

createDate(dateObj) {
    if ( dateObj == null ) {
        return null;
    }
    var nativeTimezoneOffset = new Date().getTimezoneOffset();
    var offset = this.getTimeZoneOffset();

    // use the native Date object if the timezone matches
    if ( offset == -1 * nativeTimezoneOffset ) {
        return dateObj;
    }

    this.loadTimeZones();

    // FIXME: it would be better if timezoneJS.Date was an instanceof of Date
    //        tried jquery $.extend
    //        added hack to Fiterpickr to look for Dater.getTime instead of "d instanceof Date"
    return new timezoneJS.Date(dateObj,this.getTimeZoneName());
},
Stephen Ince
źródło
-11

To jest NAJLEPSZE rozwiązanie

Za pomocą:

// TO ALL dates
Date.timezoneOffset(-240) // +4 UTC

// Override offset only for THIS date
new Date().timezoneOffset(-180) // +3 UTC

Kod:

Date.prototype.timezoneOffset = new Date().getTimezoneOffset();

Date.setTimezoneOffset = function(timezoneOffset) {
  return this.prototype.timezoneOffset = timezoneOffset;
};

Date.getTimezoneOffset = function() {
  return this.prototype.timezoneOffset;
};

Date.prototype.setTimezoneOffset = function(timezoneOffset) {
  return this.timezoneOffset = timezoneOffset;
};

Date.prototype.getTimezoneOffset = function() {
  return this.timezoneOffset;
};

Date.prototype.toString = function() {
  var offsetDate, offsetTime;
  offsetTime = this.timezoneOffset * 60 * 1000;
  offsetDate = new Date(this.getTime() - offsetTime);
  return offsetDate.toUTCString();
};

['Milliseconds', 'Seconds', 'Minutes', 'Hours', 'Date', 'Month', 'FullYear', 'Year', 'Day'].forEach((function(_this) {
  return function(key) {
    Date.prototype["get" + key] = function() {
      var offsetDate, offsetTime;
      offsetTime = this.timezoneOffset * 60 * 1000;
      offsetDate = new Date(this.getTime() - offsetTime);
      return offsetDate["getUTC" + key]();
    };
    return Date.prototype["set" + key] = function(value) {
      var offsetDate, offsetTime, time;
      offsetTime = this.timezoneOffset * 60 * 1000;
      offsetDate = new Date(this.getTime() - offsetTime);
      offsetDate["setUTC" + key](value);
      time = offsetDate.getTime() + offsetTime;
      this.setTime(time);
      return time;
    };
  };
})(this));

Wersja do kawy:

Date.prototype.timezoneOffset = new Date().getTimezoneOffset()


Date.setTimezoneOffset = (timezoneOffset)->
    return @prototype.timezoneOffset = timezoneOffset


Date.getTimezoneOffset = ->
    return @prototype.timezoneOffset


Date.prototype.setTimezoneOffset = (timezoneOffset)->
    return @timezoneOffset = timezoneOffset


Date.prototype.getTimezoneOffset = ->
    return @timezoneOffset


Date.prototype.toString = ->
    offsetTime = @timezoneOffset * 60 * 1000
    offsetDate = new Date(@getTime() - offsetTime)
    return offsetDate.toUTCString()


[
    'Milliseconds', 'Seconds', 'Minutes', 'Hours',
    'Date', 'Month', 'FullYear', 'Year', 'Day'
]
.forEach (key)=>
    Date.prototype["get#{key}"] = ->
        offsetTime = @timezoneOffset * 60 * 1000
        offsetDate = new Date(@getTime() - offsetTime)
        return offsetDate["getUTC#{key}"]()

    Date.prototype["set#{key}"] = (value)->
        offsetTime = @timezoneOffset * 60 * 1000
        offsetDate = new Date(@getTime() - offsetTime)
        offsetDate["setUTC#{key}"](value)
        time = offsetDate.getTime() + offsetTime
        @setTime(time)
        return time
Maxmaxmaximus
źródło
2
Wow, też mi się to nie podoba, ale wydaje mi się, że ludzie naprawdę nienawidzą cię, że przesłaniałeś prototyp wbudowanych plików!
Josh z Qaribou