Как получить метку времени 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(); 
}

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

15 ответов


  1. даты, построенные таким образом, используют локальный часовой пояс, делая построенную дату неправильной. Чтобы установить часовой пояс определенного объекта date, необходимо построить его из строки даты, которая включает часовой пояс. (У меня были проблемы с тем, чтобы это работало в старом браузере 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() возвращает день недели.


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

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

console.log("UTCseconds", UTCseconds)

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

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

console.log('UTCstring', UTCstring);
  

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

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


вам вообще не нужно делать много "манипуляции часового пояса" на стороне клиента. Как правило, я стараюсь хранить и работать с датами 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 вечера, дата=8/26/2014, Время=6:36:40 PM


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

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

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

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

когда вы хотите передать значение даты обратно на сервер, который вы бы назвали

someDate.toISOString();

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

someDate.getTime();

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

С 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)

EDIT: код ниже не работает. Я всегда предполагал, что новая дата().getTime () возвращает количество секунд с 1 января 1970 года в текущем часовом поясе. Это не так: getTime () возвращает количество секунд в UTC. Таким образом, приведенный ниже код делает грубую корректировку. Спасибо вам всем!]

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

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

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

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

эта функция, кажется, настоящий трюк:

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

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

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

n.getUTCUnixTime();

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

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

Merc.


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

все они идентичны, а их целочисленные значения all = = = 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/


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

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

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


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

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

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

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