Как получить временную метку UTC в JavaScript?

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

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

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

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

Date.prototype.getUTCTime = function(){ 
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime(); 
}

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

Ответы

Ответ 1

  • Даты, построенные таким образом, используют локальный часовой пояс, делая неверную дату построения. Чтобы установить часовой пояс для определенного объекта даты, необходимо построить его из строки даты, которая включает часовой пояс. (У меня были проблемы с тем, чтобы работать в старшем браузере Android.)

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

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

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

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

Чтобы уточнить:

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() возвращает день недели.

Ответ 2

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

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

Если вы хотите передать значение "Дата" на сервер, вы вызываете

someDate.toISOString();

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

someDate.getTime();

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

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

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

Ответ 5

Обычно вам не нужно выполнять большую часть "манипуляции с часовым поясом" на стороне клиента. Как правило, я стараюсь хранить и работать с датами 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>");

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

ticks = 1409103400661, DateTime = 8/26/2014 6:36:40 PM, Date = 8/26/2014, Время = 6: 36: 40 PM

Ответ 6

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

new Date().toISOString()
"2016-06-03T23:15:33.008Z"

Ответ 7

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

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

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

var utcTime = new Date().getUTCTime();

Ответ 8

Если вам нужен один лайнер, UTC Unix Timestamp может быть создан в JavaScript как:

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

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

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

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

Ответ 9

EDIT: код ниже НЕ работает. Я всегда предполагал, что новая Date(). GetTime() вернула количество секунд с 1 января 1970 года в ТЕКУЩЕМ ВРЕМЕНИ. Это не так: getTime() возвращает количество секунд в UTC. Таким образом, приведенный ниже код делает грубую чрезмерную настройку. Спасибо всем!]

Прежде всего, спасибо за ваши фантастические идеи. Думаю, у моего вопроса был неправильный заголовок... это должно было быть "Получить отметку времени UTC Unix для существующей даты".

Итак, если у меня есть объект даты:

var d = new Date(2009,01,31)

Я был после функции, которая сообщила бы мне "UTC Unix Timestamp".

Эта функция кажется настоящим трюком:

Date.prototype.getUTCUnixTime =  function (){
  return Math.floor( new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime() / 1000); 
}

Обратите внимание, что он работает на "this" Это означает, что я могу сделать:

var n = new Date(2008,10,10)
...
...

n.getUTCUnixTime();

И получите количество секунд с 1 января 1970 года во время Unix. Правильно?

Немного сумасшедший, для меня, что Javascript хранит все в UTC раз, но затем, чтобы получить этот номер, мне нужно создать новый объект Date, передающий отдельные UTC-получатели, а затем, наконец, вызвать getTime()...

Merc.

Ответ 10

Я поражен тем, насколько сложным стал этот вопрос.

Все они идентичны, а их целые значения - все === EPOCH time: D

console.log((new Date()).getTime() / 1000, new Date().valueOf() / 1000, (new Date() - new Date().getTimezoneOffset() * 60 * 1000) / 1000);

Не верьте мне, проверка: http://www.epochconverter.com/

Ответ 11

Я хочу пояснить, что новая Date(). getTime() действительно возвращает значение UTC, поэтому это действительно полезный способ хранения и управления датами способом, агностическим для локализованного времени.

Другими словами, не беспокойтесь обо всех функциях javascript UTC. Вместо этого просто используйте Date.getTime().

Дополнительная информация об этом объясняется здесь: Если javascript "(новая дата()). getTime()" запускается из двух разных часовых поясов.

Ответ 12

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

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

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0

Ответ 13

Это вернет метку времени в UTC:

var utc = new Date(new Date().toUTCString()).getTime();

Ответ 14

Я думаю, это то, чего вы ожидаете...

var currTimestamp = Date.now(), //1482905176396
    utcDateString = (new Date(currTimestamp)).toUTCString(); //"Wed, 28 Dec 2016 06:06:50 GMT"

Теперь,

new Date(utcDateString).getTime(); //This will give you UTC Timestamp in JavaScript

Ответ 15

Так как 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)