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

158

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

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

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

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

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

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

Merc
источник
Я знаю, что это довольно старый вопрос, но старайтесь не расширять нативные объекты, такие как объект Date. Проголосовал, потому что мне нравится сам вопрос.
trysis
Date.parse (new Date (). ToUTCString ())
Саги
26
Это старый вопрос, который возник сегодня в моей ленте, и он полон дезинформации. Отметка времени всегда в UTC. new Date().toString()покажет вам текущее время часовой пояс представления, new Date().toUTCString()покажет вам UTC времени магнезию, но new Date().getTime()это всегда UTC , потому что это то , что Unix время определяются как: «Unix время (также известное как POSIX времени или время эпохи) представляет собой систему для описания мгновенья во времени, определяемом как количество секунд, прошедших с 00:00:00 по всемирному координированному времени (UTC), четверг, 1 января 1970 года, без учета високосных секунд ».
Амадан

Ответы:

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

DCoder
источник
1
1) Я не создавал дату ... Я добавил функцию-прототип, которая работала над этим . 2) Хороший вопрос, я должен сделать Math.floor / 1000 - но все же мне нужна эта функция, чтобы иметь метку времени UTC для существующего объекта даты ... верно?
Merc
@Merc: 1) вы звоните new Date(), что создает новую дату из вашего ввода UTC, но обрабатывает ее как локальную дату / время. 2) Да, вы должны использовать Math.floor(this.getTime() / 1000)в этом случае.
DCoder
Отвечая здесь, как мне нужно обновить код ... Это иметь метку времени Unix в UTC для существующей даты: 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.getUTCTime (); (Это будет ОТЛИЧНО от n.getUTCTime ())
Merc
1
Спасибо, братан. Его рабочий файл Math.floor ((new Date ()). GetTime () / 1000)
Манодж Патель
51

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

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

console.log("UTCseconds", UTCseconds)

Шиплу Мокаддим
источник
4
Спасибо, этого нигде нет в интернете!
Феофанис Пантелидес
Я проверить следующие коды: var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000. Кажется, tt.getTime() - tt.getTimezoneOffset()это правильно для GMT+0800.
Zangw
1
Это лучшеvar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya
Похоже, что это не работает так, как написано. Похоже, вы должны передать временную строку, new Date()которая включает в себя часовой пояс ... который побеждает цель попытки сделать это в js ..
claudekennilol
Это просто неправильно, значение, назначенное для UTCseconds , не является UTC секундами. Значение времени Date является UTC, изменение его любым способом означает, что оно представляет другой момент времени.
RobG
35

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

new Date().toISOString()
"2016-06-03T23:15:33.008Z"
Тахсин Туркоз
источник
3
Это правильный ответ. Многие другие ответы дают «универсальную временную строку», но не дают текущего «универсального скоординированного времени». Я не понимаю, почему здесь все так сложно.
Гбертон
Спасибо @gburton. Ценю, вы видите простой путь к истине. :)
Тахсин Туркоз
1
Я использую это, вместе с ".split ('T') [0]" для простых сравнений на основе даты в ГГГГ-ММ-ДД.
Шон О
Приятно иметь @SeanO
Tahsin Turkoz
Это обеспечивает строку времени UTC, но OP запрашивает
Jordi
13

Я действительно думаю, что значения 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 делает это довольно тривиальным.

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

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

Мэтт Эш
источник
12

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

ahmd0
источник
1
Добавляя getTimezoneOffsetзначение в вашу getCurrentTimeUTCфункцию, вы фактически возвращаете другой момент времени. Результатом getTimeявляется уже в UTC.
Мэтт Джонсон-Пинт
1
@MattJohnson: это неправильно. Результатом tmLoc.getTime()является смещение относительно местного времени. Это легко проверить, если у вас есть доступ ко всему, что работает с JavaScript.
ahmd0
2
Извините, но это не так. Смотрите ссылку на MDN . Вы также можете увидеть это в спецификации ECMAScript. В п. 15.9.3.3 описываетсяgetTime , что указывает на «значение времени», определенное в п. 15.9.5 , которое PrimitiveValueустановлено в явном виде в п. 15.9.3.3 как UTC.
Мэтт Джонсон-Пинт
2
Ну, так как вы получаете tmLocчерез new Date(), то это то же самое. Часовой пояс повлияет на вывод строки tmLoc.toString()и аналогичных элементов, но не повлияет. tmLoc.getTime() Это всегда всего несколько миллисекунд с полуночи 1970-01-01 в UTC.
Мэтт Джонсон-Пинт
1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0
5

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

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

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0
koalex
источник
Еще один неправильный ответ, getTime возвращает смещение UTC, добавляя смещение локального часового пояса, что полностью портит его. Смещения ECMAScript: + ve для запада и -ve для востока, поэтому их нужно вычесть из UTC, чтобы получить местный. Но так как значение времени UTC для начала, добавление его существенно сдвигает его от UTC в направлении, противоположном локальному смещению.
RobG
4

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

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

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

Как это устроено:

  • Создать объект даты: new Date() .
  • Преобразовать в метку времени, добавив unary +перед созданием объекта для преобразования в timestamp integer. :+new Date() .
  • Преобразовать миллисекунды в секунды: +new Date() / 1000
  • Используйте двойные тильды, чтобы округлить значение до целого числа. :~~(+new Date())
Кушал Лихи
источник
7
это tildeне tilda(так). К сожалению, это не позволит мне удалить опечатку, я должен сделать как минимум 6 правок символов. Гладкий, Stackexchange, гладкий
Фред
3
Не используйте это . С текущей спецификацией ecma побитовые операции (например, тильда - побитовая нет) обрабатывают целочисленные значения со знаком в 32 бита. Это означает, что эта магия тильды не будет работать после 19 января 2038 года, когда значение временной метки превысит максимальное значение 32-разрядного целого числа со знаком. jsfiddle.net/phb20ymb
Sharky
3

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

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

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

Стэн Лин
источник
3

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

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

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

var utcTime = new Date().getUTCTime();
jlbofh
источник
Самое чистое решение. СПАСИБО!
лавина1
Но это не чистое решение для отправки дат, потому что метки времени всегда в формате UTC. Лучшее решение для меня при отправке дат - это использовать строковое представление типа «дд / мм / гггг ЧЧ: мм: сс», а затем проанализировать его на стороне сервера со стандартной часовой поясом сервера, чтобы получить метку времени UTC или что-то еще. Смотрите этот ответ
jlbofh
2
Разбор строки - вы называете это чистым? Мех
лавина1
Убедитесь, что есть методы для генерации даты в строковом формате в соответствии со спецификациями ISO. Метод isISttring (). Вы можете разобрать это чисто в Java, используя что-то вроде:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh
Другой неправильный ответ this.getTime()возвращает смещение UTC, вычитая смещение локального часового пояса, делает его локальным, а не UTC, поэтому getUTCTime возвращает локальное смещение, а не UTC.
RobG
2

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

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

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

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

fliptopbox
источник
2

Так как 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)
Морис Випф
источник
1

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

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

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

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); 
}

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

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

n.getUTCUnixTime();

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

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

Merc.

Merc
источник
1
Вы видели обновление @ DCoder к его ответу? Ваш метод getUTCUnixTimeполучает неправильное время, а JavaScript действительно предоставляет простой способ получить метку времени Unix от Dateобъекта - используя getTimeметод. Посмотреть все остальные ответы.
Anurag
1
Тьфу, ты прав, просто видел их. (Бьется головой об стену)
Merc
1

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

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
Kapilrc
источник
0

Как только вы это сделаете

new Date(dateString).getTime() / 1000

Это уже время UTC

   const getUnixTimeUtc = (dateString = new Date()) => Math.round(new Date(dateString).getTime() / 1000)

Я тестировал на https://www.unixtimestamp.com/index.php

fiddlest
источник
0

Использование day.js

В браузере:

dayjs.extend(dayjs_plugin_utc)
console.log(dayjs.utc().unix())
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/plugin/utc.js"></script>

В node.js:

import dayjs from 'dayjs'
dayjs.extend(require('dayjs/plugin/utc'))
console.log(dayjs.utc().unix())

Вы получите UTC Unix Timestamp без миллисекунд.

Ильич
источник
-2

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

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

Яш Пандя
источник
2
Это не возвращает время в UTC: new Date(new Date().toUTCString())дает ср. 04 октября 2017 г. 07:20:14 GMT + 0200 (GMT + 02: 00)
Bas van Dijk