Как конвертировать дату JavaScript в UTC?
Предположим, что пользователь вашего сайта вводит диапазон дат.
2009-1-1 to 2009-1-3
Вам необходимо отправить эту дату на сервер для некоторой обработки, но сервер ожидает, что все даты и время будут в UTC.
Теперь предположим, что пользователь находится на Аляске, Гавайях или Фиджи. Так как они находятся в часовом поясе, весьма отличном от UTC, диапазон дат необходимо преобразовать во что-то вроде этого:
2009-1-1T8:00:00 to 2009-1-4T7:59:59
Используя объект Date в JavaScript, как бы вы преобразовали первый "локализованный" диапазон дат в то, что сервер поймет?
37 ответов
toISOString()
Метод возвращает строку в упрощенном расширенном формате ISO ( ISO 8601), длина которого всегда 24 или 27 символов (YYYY-MM-DDTHH:mm:ss.sssZ
или же±YYYYYY-MM-DDTHH:mm:ss.sssZ
соответственно). Часовой пояс всегда равен нулевому смещению UTC, как обозначено суффиксом "Z
".
Источник: MDN веб-документы
Необходимый формат создается с помощью .toISOString()
метод. Для более старых браузеров (т.е. 8 и ниже), которые изначально не поддерживают этот метод, шим можно найти здесь:
Это даст вам возможность делать то, что вам нужно:
var isoDate = new Date('yourdatehere').toISOString();
Для работы с часовым поясом, zone.js и moment.js являются действительно бесценными инструментами... особенно для навигации по часовым поясам между клиентом и сервером javascript.
Просто и глупо
var date = new Date();
var now_utc = Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(),
date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
return new Date(now_utc);
Вот мой метод:
var now = new Date();
var utc = new Date(now.getTime() + now.getTimezoneOffset() * 60000);
Результирующий utc
Объект на самом деле не является датой UTC, но локальная дата смещена в соответствии с временем UTC (см. комментарии). Однако на практике это делает работу.
Конвертировать в ISO без изменения даты / времени
var now = new Date(); // Fri Feb 20 2015 19:29:31 GMT+0530 (India Standard Time)
var isoDate = new Date(now.getTime() - now.getTimezoneOffset() * 60000).toISOString();
//OUTPUT : 2015-02-20T19:29:31.238Z
Конвертировать в ISO с изменением даты / времени (дата / время будут изменены)
isoDate = new Date(now).toISOString();
//OUTPUT : 2015-02-20T13:59:31.238Z
Другое решение для преобразования в UTC и сохранения его как объекта даты: (Он работает, удаляя часть ' GMT' из конца отформатированной строки, а затем возвращая ее обратно в конструктор Date)
var now = new Date();
var now_utc = new Date(now.toUTCString().slice(0, -4));
Мне нужно было сделать это для взаимодействия с библиотекой выбора даты и времени. Но в целом работать с датами в таком случае - плохая идея.
Пользователи обычно хотят работать с датами и временем по местному времени, поэтому вы либо обновляете код на стороне сервера, чтобы правильно анализировать строки даты и времени со смещениями, затем конвертируете в UTC (лучший вариант) или конвертируете в строку UTC на стороне клиента перед отправкой в сервер (как в ответе Уилла Стерна)
Date.prototype.toUTCArray= function(){
var D= this;
return [D.getUTCFullYear(), D.getUTCMonth(), D.getUTCDate(), D.getUTCHours(),
D.getUTCMinutes(), D.getUTCSeconds()];
}
Date.prototype.toISO= function(){
var tem, A= this.toUTCArray(), i= 0;
A[1]+= 1;
while(i++<7){
tem= A[i];
if(tem<10) A[i]= '0'+tem;
}
return A.splice(0, 3).join('-')+'T'+A.join(':');
}
В моем решении дата остается неизменной независимо от того, какой часовой пояс установлен на стороне клиента. Может кому пригодится.
Мой вариант использования:
Я создаю приложение todo, в котором вы устанавливаете дату своей задачи. Эта дата должна оставаться постоянной независимо от того, в каком часовом поясе вы находитесь.
Пример. Вы хотите позвонить другу в 8 утра 25 июня.
Вы создаете это задание за 5 дней до (20 июня), пока находитесь в Китае.
Затем в тот же день вы на несколько дней летите в Нью-Йорк.
Затем 25 июня, пока вы все еще в Нью-Йорке, вы просыпаетесь в 7:30 утра (что означает, что вы должны получить уведомление о задаче через 30 минут (даже несмотря на то, что уже 13:30 в Китае, где вы были при создании задача)
Таким образом, задача игнорировать часовой пояс. Это означает: "Я хочу сделать это в 8 часов утра в любом часовом поясе, в котором я буду".
Что я делаю, так это скажу: "Я полагаю, вы всегда находитесь в часовом поясе Лондона - UTC".
Это означает, что когда пользователь выбирает дату в своем часовом поясе, я конвертирую эту дату в ту же дату в формате UTC. т.е. Вы выбираете 8 часов утра в Китае, но я конвертирую его в 8 часов утра по всемирному координированному времени.
Затем - в следующий раз, когда вы откроете приложение - я читаю дату, сохраненную в формате UTC, и конвертирую ее в ту же дату в вашем текущем часовом поясе, например. Я конвертирую 8 часов утра по всемирному координированному времени в 8 часов утра по часовому поясу Нью-Йорка.
Это решение означает, что дата может означать что-то еще, в зависимости от того, где вы находитесь при ее установке и где вы ее читаете, но она остается постоянной, так что создается ощущение, что вы всегда находитесь в одном часовом поясе.
Напишем код:
Во-первых, у нас есть 2 основные функции для преобразования из / в UTC без учета часового пояса:
export function convertLocalDateToUTCIgnoringTimezone(date: Date) {
const timestamp = Date.UTC(
date.getFullYear(),
date.getMonth(),
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
date.getMilliseconds(),
);
return new Date(timestamp);
}
export function convertUTCToLocalDateIgnoringTimezone(utcDate: Date) {
return new Date(
utcDate.getUTCFullYear(),
utcDate.getUTCMonth(),
utcDate.getUTCDate(),
utcDate.getUTCHours(),
utcDate.getUTCMinutes(),
utcDate.getUTCSeconds(),
utcDate.getUTCMilliseconds(),
);
}
Затем я сохраняю / читаю эту дату как:
function saveTaskDate(localDate: Date) {
// I convert your local calendar date so it looks like you've picked it being in UTC somewhere around London
const utcDate = convertLocalDateToUTCIgnoringTimezone(localDate);
api.saveTaskDate(utcDate);
}
function readTaskDate(taskUtcDate: Date) {
// I convert this UTC date to 'look in your local timezone' as if you were now in UTC somewhere around london
const localDateWithSameDayAsUTC = convertUTCToLocalDateIgnoringTimezone(taskUtcDate);
// this date will have the same calendar day as the one you've picked previously
// no matter where you were saving it and where you are now
}
Браузеры могут отличаться, и вы также должны помнить, что не следует доверять какой-либо информации, сгенерированной клиентом, поскольку, как говорится, нижеприведенное утверждение работает для меня (Google Chrome v24 в Mac OS X 10.8.2)
var utcDate = new Date(new Date().getTime());
Редактировать: "Как это отличается от всего new Date()
?"см. здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
- Если аргументы не предоставлены, конструктор создает объект JavaScript Date для текущей даты и времени в соответствии с настройками системы.
- Примечание. Если Date вызывается как конструктор с более чем одним аргументом, указанные аргументы представляют собой местное время. Если требуется UTC, используйте новую дату ( Date.UTC (...)) с теми же аргументами. (примечание: Date.UTC() возвращает количество миллисекунд с 1970-01-01 00:00:00 UTC)
Добавление 60000 * Date.getTimezoneOffset(), как указано в предыдущих ответах, неверно. Во-первых, вы должны думать обо всех датах / временах как о времени UTC с модификатором часового пояса для целей отображения.
Опять же, браузеры могут отличаться, однако Date.getTime() возвращает количество миллисекунд с 1970-01-01 UTC/GMT. Если вы создадите новую дату, используя этот номер, как я делаю выше, это будет UTC / GMT. Однако, если вы отобразите его, вызвав.toString(), он окажется в вашем местном часовом поясе, потому что.toString() использует ваш местный часовой пояс, а не часовой пояс объекта Date, для которого он вызывается.
Я также обнаружил, что если вы вызываете.getTimezoneOffset () для даты, она вернет ваш местный часовой пояс, а не часовой пояс объекта даты, для которого вы его вызвали (однако я не могу проверить, чтобы это было стандартным).
В моем браузере добавление 60000 * Date.getTimezoneOffset() создает DateTime, который не является UTC. Однако, когда отображается в моем браузере (например: .toString()), он отображает DateTime в моем местном часовом поясе, который будет правильным временем UTC, если информация о часовом поясе игнорируется.
var myDate = new Date(); // Set this to your date in whichever timezone.
var utcDate = myDate.toUTCString();
date = '2012-07-28'; stringdate = new Date(date).toISOString();
должен работать в большинстве новых браузеров. это возвращается 2012-07-28T00:00:00.000Z
на Firefox 6.0
Вы пытаетесь преобразовать дату в такую строку?
Я бы сделать функцию, чтобы сделать это, и, хотя это немного спорно, добавить его к дате прототипа. Если вам неудобно делать это, то вы можете поместить это как отдельную функцию, передавая дату в качестве параметра.
Date.prototype.getISOString = function() {
var zone = '', temp = -this.getTimezoneOffset() / 60 * 100;
if (temp >= 0) zone += "+";
zone += (Math.abs(temp) < 100 ? "00" : (Math.abs(temp) < 1000 ? "0" : "")) + temp;
// "2009-6-4T14:7:32+10:00"
return this.getFullYear() // 2009
+ "-"
+ (this.getMonth() + 1) // 6
+ "-"
+ this.getDate() // 4
+ "T"
+ this.getHours() // 14
+ ":"
+ this.getMinutes() // 7
+ ":"
+ this.getSeconds() // 32
+ zone.substr(0, 3) // +10
+ ":"
+ String(temp).substr(-2) // 00
;
};
Если вам это нужно во время UTC, просто замените все функции get* на getUTC*, например: getUTCFullYear, getUTCMonth, getUTCHours..., а затем просто добавьте "+00:00" в конце вместо смещения часового пояса пользователя.
Моя рекомендация при работе с датами состоит в том, чтобы разбить дату на отдельные поля из пользовательского ввода. Вы можете использовать его как полную строку, но вы играете с огнем.
JavaScript может обрабатывать две одинаковые даты в разных форматах по-разному.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
Никогда не делайте ничего подобного:
new Date('date as text');
После того как ваша дата будет проанализирована в отдельных полях из пользовательского ввода, создайте объект даты. Как только объект даты создан, преобразуйте его в UTC, добавив смещение часового пояса. Я не могу не подчеркнуть, насколько важно использовать смещение от объекта даты из-за перехода на летнее время (это еще одно обсуждение, чтобы показать, почему).
var year = getFullYear('date as text');
var month = getMonth('date as text');
var dayOfMonth = getDate('date as text');
var date = new Date(year, month, dayOfMonth);
var offsetInMs = ((date.getTimezoneOffset() * 60) // Seconds
* 1000); // Milliseconds
var utcDate = new Date(date.getTime + offsetInMs);
Теперь вы можете передать дату на сервер по UTC времени. Опять же, я бы настоятельно рекомендовал не использовать любые строки даты. Либо передайте его на сервер с минимальной степенью детализации, необходимой вам, например, год, месяц, день, минута, либо в виде значения, например, в миллисекундах с эпохи Unix.
Если вы много имеете дело с датами, стоит использовать moment.js ( http://momentjs.com/). Метод для преобразования в UTC будет:
moment(yourTime).utc()
Вы можете использовать формат для изменения даты на любой другой формат:
moment(yourTime).utc().format("YYYY-MM-DD")
Также есть опции смещения в данный момент, но есть дополнительная дополнительная библиотека для работы с часовым поясом ( http://momentjs.com/timezone/). Преобразование времени будет так просто:
moment.tz(yourUTCTime, "America/New_York")
Я нашел, что анализ даты плагинов глобализации jQuery работает лучше всего. Другие методы имели проблемы с кроссбраузерностью, и такие вещи, как date.js, давно не обновлялись.
Вам также не нужен DatePicker на странице. Вы можете просто вызвать что-то похожее на пример, приведенный в документации:
$.parseDate('yy-mm-dd', '2007-01-26');
Метод getTimezoneOffset() возвращает разницу часовых поясов в минутах от текущего языкового стандарта (настройки хост-системы) до UTC.
Источник: веб-документы MDN.
Это означает, что смещение положительное, если местный часовой пояс отстает от UTC, и отрицательное, если оно впереди. Например, для часового пояса UTC+02:00, -120 , будут возвращены.
ПРИМЕЧАНИЕ. Это приведет к сдвигу времени объекта даты на UTC±00:00 и не к преобразованию его часового пояса, поэтому часовой пояс объекта даты останется прежним, но значение будет в UTC±00:00 .
Использование UTC метода moment.js;
const moment = require('moment');
const utc = moment.utc(new Date(string));
Я только что обнаружил, что версия date.format.js Стивена Левитана 1.2.3 делает именно то, что я хочу. Это позволяет вам предоставить строку формата для даты JavaScript и конвертировать из местного времени в UTC. Вот код, который я сейчас использую:
// JavaScript dates don't like hyphens!
var rectifiedDateText = dateText.replace(/-/g, "/");
var d = new Date(rectifiedDateText);
// Using a predefined mask from date.format.js.
var convertedDate = dateFormat(d, 'isoUtcDateTime');
Для других людей, цель которых - получить его как «объект даты», а не как строку, и вы хотите отображать только дату / время без TZ (вероятно, жестко запрограммированного), вы можете сделать следующее:
const now = new Date();
const year = now.getUTCFullYear();
const month = now.getUTCMonth();
const day = now.getUTCDate();
const hour = now.getUTCHours();
const tomorrowUTC= new Date();
tomorrowUTC.setDate(day + 1); // +1 because my logic is to get "tomorrow"
tomorrowUTC.setYear(year);
tomorrowUTC.setMonth(month);
tomorrowUTC.Hours(hour);
// then use the tomorrowUTC for to display/format it
// tomorrowUTC is a "Date" and not a string.
Затем вы можете делать что-то вроде:
We will delete your account at ${format(tomorrowUTC, 'EEEE do MMMM hh:mmaaa')} UTC
(
format
это функция date-fns , вы можете использовать другую библиотеку, если хотите);
Это своего рода "хакерство", поскольку здесь все еще используется ваш местный часовой пояс, но если вы просто хотите отображать дату, а не часовой пояс, тогда это работает.
Этот метод даст вам: 2017-08-04T11:15:00.000+04:30
и вы можете игнорировать переменную зоны, чтобы просто получить 2017-08-04T11:15:00.000
,
function getLocalIsoDateTime(dtString) {
if(dtString == "")
return "";
var offset = new Date().getTimezoneOffset();
var localISOTime = (new Date(new Date(dtString) - offset * 60000 /*offset in milliseconds*/)).toISOString().slice(0,-1);
//Next two lines can be removed if zone isn't needed.
var absO = Math.abs(offset);
var zone = (offset < 0 ? "+" : "-") + ("00" + Math.floor(absO / 60)).slice(-2) + ":" + ("00" + (absO % 60)).slice(-2);
return localISOTime + zone;
}
Это то, что я сделал в прошлом:
var utcDateString = new Date(new Date().toUTCString()).toISOString();
Эта функция прекрасно работает для меня.
function ParseDateForSave(dateValue) {
// create a new date object
var newDate = new Date(parseInt(dateValue.substr(6)));
// return the UTC version of the date
return newDate.toISOString();
}
Если вам нужен объект Date
Передача только строки даты Date предполагает, что время сдвигается на 00:00 по часовому поясу:
new Date('2019-03-11')
Sun Mar 10 2019 18:00:00 GMT-0600 (Central Standard Time)
Если вы добавите текущие часы и минуты, вы получите правильную дату:
new Date('2019-03-11 ' + new Date().getHours() + ':' + new Date().getMinutes())
Mon Mar 11 2019 04:36:00 GMT-0600 (Central Standard Time)
Если на вашей дате указан часовой пояс, вы можете использовать date-fns-tz:
import { zonedTimeToUtc } from 'date-fns-tz';
const dateBrazil = new Date() // I'm in Brazil, you should have or get the user timezone.
const dateUtc = zonedTimeToUtc(dateBrazil, 'America/Sao_Paulo')
var userdate = new Date("2009-1-1T8:00:00Z");
var timezone = userdate.getTimezoneOffset();
var serverdate = new Date(userdate.setMinutes(userdate.getMinutes()+parseInt(timezone)));
Это даст вам правильную дату и время UTC.
Это потому что getTimezoneOffset()
даст вам разницу часовых поясов в минутах. Я рекомендую вам не использовать toISOString()
потому что вывод будет в строке, следовательно, в будущем вы не сможете манипулировать датой
Глядя на ваш вопрос, становится ясно, что вы просто хотите отправить диапазон дат в свой бэкэнд для дальнейшей постобработки.
Я предполагаю, что вы соответствуете стандартным рекомендациям по данным, которые предполагают, что данные будут в определенном формате. Например, я использую ODATA, который является API RESTfull, который ожидает, что объекты даты и времени будут в формате:-
YYYY-MM-DDT00: 00: 00.
Это может быть легко достигнуто с помощью фрагмента, размещенного ниже (Пожалуйста, измените формат в соответствии с вашими требованиями).
var mydate;//assuming this is my date object which I want to expose
var UTCDateStr = mydate.getUTCFullYear() + "-" + mydate.getUTCMonth() + "-" + mydate.getUTCDate() + "T00:00:00";
Если, с другой стороны, вы находитесь в моей ситуации, когда вы получили дату от своего бэкэнда, и браузер преобразует ее в вашу локальную дату. Вы, с другой стороны, заинтересованы в дате UTC, тогда вы можете выполнить следующее:-
var mydate;//assuming this is my date object which I want to expose
var UTCDate = new Date(mydate);/*create a copy of your date object. Only needed if you for some reason need the original local date*/
UTCDate.setTime(UTCDate.getTime() + UTCDate.getTimezoneOffset() * 60 * 1000);
Приведенный выше фрагмент кода в основном добавляет / вычитает время, добавляемое / вычитаемое браузером, на основе часового пояса.
Например, если я нахожусь в EST(GMT-5) и моя служба возвращает объект даты и времени = ср. 17 августа 2016 00:00:00 GMT-0500, мой браузер автоматически вычитает смещение часового пояса (5 часов), чтобы узнать мое местное время. Поэтому, если я попытаюсь получить время, то получу ср. 16 августа 2016 г. 19:00:00 GMT-0500. Это вызывает много проблем. Есть много библиотек, которые определенно сделают это проще, но я хотел бы поделиться подходом чистого JS.
Для получения дополнительной информации, пожалуйста, посмотрите на: http://praveenlobo.com/blog/how-to-convert-javascript-local-date-to-utc-and-utc-to-local-date/ где я получил мой вдохновение.
Надеюсь это поможет!
Используя моментальный пакет, вы можете легко преобразовать строку даты UTC в новый объект Date:
const moment = require('moment');
let b = new Date(moment.utc('2014-02-20 00:00:00.000000'));
let utc = b.toUTCString();
b.getTime();
Это особенно помогает, когда ваш сервер не поддерживает часовой пояс, и вы хотите всегда сохранять дату UTC на сервере и возвращать ее как новый объект Date. Выше код работал для моего требования аналогичной проблемы, что этот поток для. Поделиться здесь, чтобы помочь другим. Я не вижу точно вышеуказанного решения ни в одном ответе. Благодарю.
Const event = новая дата ();
console.log(event.toUTCString());
Безусловно, лучший способ узнать время по Гринвичу - это сначала узнать местное время. Затем преобразуйте в строку GMT. Затем используйте строку, чтобы построить новое время, удалив часовой пояс.
let dtLocal = new Date()
let dt = new Date(dtLocal.toISOString().split('Z')[0])
Примечание: - он создаст новую дату и время в GMT. Но это будет местное время, так как к нему будет привязан часовой пояс.
Вы можете использовать следующий метод для преобразования любой даты js в UTC:
let date = new Date(YOUR_DATE).toISOString()
// It would give the date in format "2020-06-16T12:30:00.000Z" where Part before T is date in YYYY-MM-DD format, part after T is time in format HH:MM:SS and Z stands for UTC - Zero hour offset
Я знаю, что этот вопрос старый, но рассматривал эту же проблему, и одним из вариантов было бы вместо этого отправить date.valueOf() на сервер. Функция valueOf () javascript Date отправляет количество миллисекунд с полуночи 1 января 1970 года UTC.