Как получить метку времени UTC в JavaScript? - PullRequest
137 голосов
/ 18 марта 2012

При написании веб-приложения имеет смысл хранить (на стороне сервера) все даты и времени в БД в качестве меток времени UTC.

Я был удивлен, когда заметил, что вы не можете сделать многое с точки зрения манипуляции с часовым поясом в JavaScript.

Я немного расширил объект Date. Имеет ли эта функция смысл? По сути, каждый раз, когда я отправляю что-либо на сервер, это будет отметка времени, отформатированная с помощью этой функции ...

Вы видите здесь какие-либо серьезные проблемы? Или, может быть, решение под другим углом?

* * 1010

Мне это кажется немного запутанным. И я не так уверен в производительности.

Ответы [ 15 ]

133 голосов
/ 18 марта 2012
  1. Для дат, построенных таким образом, используется местный часовой пояс, что делает построенную дату неправильной. Чтобы установить часовой пояс для определенного объекта даты, нужно построить его из строки даты, которая включает часовой пояс. (У меня были проблемы с тем, чтобы это работало в старом браузере Android.)

  2. Обратите внимание, что getTime() возвращает миллисекунды, а не обычные секунды.

Для отметки времени UTC / Unix должно быть достаточно:

Math.floor((new Date()).getTime() / 1000)

Он будет учитывать текущее смещение часового пояса в результате. Для строкового представления, Дэвид Эллис ' ответ работает.

уточнить:

new Date(Y, M, D, h, m, s)

Этот ввод обрабатывается как местное время . Если введено UTC время , результаты будут отличаться. Заметьте (сейчас я в GMT +02: 00, а сейчас 07:50):

> var d1 = new Date();
> d1.toUTCString();
"Sun, 18 Mar 2012 05:50:34 GMT" // two hours less than my local time
> Math.floor(d1.getTime()/ 1000)
1332049834 

> var d2 = new Date( d1.getUTCFullYear(), d1.getUTCMonth(), d1.getUTCDate(), d1.getUTCHours(), d1.getUTCMinutes(), d1.getUTCSeconds() );
> d2.toUTCString();
"Sun, 18 Mar 2012 03:50:34 GMT" // four hours less than my local time, and two hours less than the original time - because my GMT+2 input was interpreted as GMT+0!
> Math.floor(d2.getTime()/ 1000)
1332042634

Также обратите внимание, что getUTCDate() нельзя заменить на getUTCDay(). Это потому, что getUTCDate() возвращает день месяца ; тогда как getUTCDay() возвращает день недели .

48 голосов
/ 18 марта 2012

Вы также можете сделать это, используя getTimezoneOffset и getTime,

x = new Date()
var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000)/1000;

console.log("UTCseconds", UTCseconds)
42 голосов
/ 18 марта 2012

Да, вам не нужно так много делать;при условии, что я вас правильно понимаю, вы просто хотите метод toUTCString .

var UTCstring = (new Date()).toUTCString();

console.log('UTCstring', UTCstring);
  

Однако помните, что значения даты, которые вы получаете, основаны на часах компьютера клиента, а не вашего сервера.Если вам нужны точные значения для этих дат (например, чтобы правильно упорядочить, когда было выполнено то или иное действие относительно действия другого пользователя), вы не можете полагаться на библиотеку дат на стороне клиента, в любом случае,и вам нужно рассчитать даты на стороне сервера, основываясь на том, когда клиент связался с вами.

Помните также, что в основном весь ваш код на стороне клиента может быть изменен клиентом, и вместо него могут быть возвращены вредоносные значения, вы можетегарантировать только код на стороне сервера - относитесь к клиенту как к возможному злоумышленнику.

14 голосов
/ 26 августа 2014

Как правило, вам не нужно выполнять «манипулирование часовым поясом» на стороне клиента. Как правило, я стараюсь хранить и работать с датами UTC в виде ticks или « числа миллисекунд с полуночи 1 января 1970 года ». Это действительно упрощает хранение, сортировку, вычисление смещений и, что самое главное, избавляет вас от головной боли от настроек перехода на летнее время. Вот небольшой код JavaScript, который я использую.

Чтобы узнать текущее время UTC:

function getCurrentTimeUTC()
{
    //RETURN:
    //      = number of milliseconds between current UTC time and midnight of January 1, 1970
    var tmLoc = new Date();
    //The offset is in minutes -- convert it to ms
    return tmLoc.getTime() + tmLoc.getTimezoneOffset() * 60000;
}

Тогда вам обычно нужно отформатировать дату / время для конечного пользователя для его локального часового пояса и формата. Следующие вопросы решают все сложности форматов даты и времени на клиентском компьютере:

function formatDateTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date/time
    return new Date(nTicks).toLocaleString();
}

function formatDateFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date
    return new Date(nTicks).toLocaleDateString();
}

function formatTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted time
    return new Date(nTicks).toLocaleTimeString();
}

Итак, следующий пример:

var ticks = getCurrentTimeUTC();  //Or get it from the server

var __s = "ticks=" + ticks + 
    ", DateTime=" + formatDateTimeFromTicks(ticks) +
    ", Date=" + formatDateFromTicks(ticks) +
    ", Time=" + formatTimeFromTicks(ticks);

document.write("<span>" + __s + "</span>");

Возвращает следующее (для моего английского языка в США):

тиков = 1409103400661, DateTime = 8/26 / 2014 6:36:40 PM, Date = 8/26 / 2014, Время = 6: 36: 40 PM

12 голосов
/ 18 марта 2012

Я действительно думаю, что значения Date в js намного лучше, чем, скажем, объекты C # DateTime.У объектов C # DateTime есть свойство Kind, но нет строгого базового часового пояса как такового, и преобразования часового пояса трудно отследить, если вы выполняете преобразование между двумя не UTC и нелокальными временами.В js все значения Date имеют базовое значение UTC, которое передается и известно независимо от выполняемых вами преобразований оффлайн или часовых поясов.Моя самая большая жалоба на объект Date - это количество неопределенного поведения, которое разработчики браузера решили включить, что может спутать людей, которые атакуют даты в js методом проб и ошибок, чем чтением спецификации.Использование чего-то вроде iso8601.js решает эту проблему, определяя единственную реализацию объекта Date.

По умолчанию в спецификации говорится, что вы можете создавать даты в расширенном формате даты ISO 8601, например

var someDate = new Date('2010-12-12T12:00Z');

Таким образом, вы можете определить точное время UTC таким образом.

Если вы хотите передать значение Date обратно на сервер, вы должны позвонить

someDate.toISOString();

или, если вы предпочитаете работать с меткой времени в миллисекундах (количество миллисекунд с 1 января 1970 года по Гринвичу))

someDate.getTime();

ISO 8601 является стандартом.Вы не можете быть смущены тем, что означает строка даты, если вы включите смещение даты.Для вас как для разработчика это означает, что вам никогда не придется самостоятельно разбираться с местным временем .Значения местного времени существуют исключительно для удобства пользователя, а значения даты по умолчанию отображаются в их местном времени.Все манипуляции с местным временем позволяют отображать что-то разумное для пользователя и преобразовывать строки из пользовательского ввода.Хорошей практикой является преобразование в UTC, как только вы сможете, и объект js Date делает это довольно тривиальным.

С другой стороны, у нас не так много возможностей для принудительного установки часового пояса или локали для клиента (что мне известно), что может раздражать настройки конкретного веб-сайта, но я полагаю, причина этого в том, что к пользовательской конфигурации не следует прикасаться.

Итак, короче говоря, причинадля манипуляций с часовыми поясами не так уж много поддержки, потому что вы просто не хотите этого делать.

11 голосов
/ 04 июня 2016

Самый простой способ получить время UTC в обычном формате заключается в следующем:

new Date().toISOString()
"2016-06-03T23:15:33.008Z"
4 голосов
/ 07 декабря 2016

Я думаю, что это лучшее решение

// UTC milliseconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0
4 голосов
/ 24 ноября 2016

Я использую следующее:

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

После определения этого метода вы можете сделать:

var utcTime = new Date().getUTCTime();
4 голосов
/ 27 марта 2015

Если вы хотите один вкладыш , UTC Unix Timestamp можно создать в JavaScript как:

var currentUnixTimestap = ~~(+new Date() / 1000);

Это будет учитывать часовой пояссистема.Время в секундах с начала эпохи.

Как это работает:

  • Создание объекта даты: new Date().
  • Преобразование в метку времени путем добавления unary + перед созданием объекта, чтобы преобразовать его в timestamp integer.: +new Date().
  • Преобразование миллисекунд в секунды: +new Date() / 1000
  • Используйте двойные тильды для округления значения до целого числа.: ~~(+new Date())
2 голосов
/ 11 октября 2017

Так как new Date().toUTCString() возвращает строку типа "Wed, 11 Oct 2017 09:24:41 GMT", вы можете нарезать последние 3 символа и передать нарезанную строку в new Date():

new Date()
// Wed Oct 11 2017 11:34:33 GMT+0200 (CEST)

new Date(new Date().toUTCString().slice(0, -3))
// Wed Oct 11 2017 09:34:33 GMT+0200 (CEST)
...