Как конвертировать дату 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.

ценность()

Другие вопросы по тегам