Як отримати часову позначку UTC у JavaScript?


157

Під час написання веб-програми, має сенс зберігати (серверно) всі дати в БД як часові позначки UTC.

Я був здивований, коли помітив, що ти не міг би зробити багато чого з точки зору маніпуляцій Timezone в JavaScript.

Я трохи подовжив об’єкт Date. Чи має ця функція сенс? По суті, кожен раз, коли я надсилаю що-небудь на сервер, це буде часова марка, відформатована за допомогою цієї функції ...

Чи можете ви побачити тут якісь основні проблеми? А може бути рішення з іншого кута?

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

Мені це здається трохи заплутаним. І я не дуже впевнений у виконанні.


Я знаю, що це якесь старе питання, але намагайтеся не поширювати натільні об’єкти, як об'єкт Date. Оновлено, тому що мені подобається саме питання.
трис

Date.parse (нова дата (). ToUTCString ())
Сагі

25
Це старе питання, яке сьогодні з’явилось у моєму каналі, і воно сповнене дезінформації. Часова позначка завжди в 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()повертає день тижня .


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 (нова дата (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 ((нова дата ()). GetTime () / 1000)
Manoj Patel

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

Це просто неправильно, значення, присвоєне UTCсекундам , не є UTC секундам. Значення дати - це UTC, змінюючи його будь-яким методом, що означає, що це інший момент часу.
RobG

34

Найпростіший спосіб отримати час UTC у звичайному форматі:

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

3
Це правильна відповідь. Багато інших відповідей дають "універсальний часовий рядок", але не дають поточного "універсального координованого часу". Я не розумію, чому тут все так складно.
gburton

Дякую @gburton Вдячний, що ви бачите простий шлях до істини. :)
Тахсін Туркоз

1
Я використовую це разом із ".split (" T ") [0]" для легкого порівняння на основі дат "РРРР-MM-DD".
Шон O

Приємно мати @SeanO
Тахсін Туркоз

Це забезпечує часовий рядок UTC, але ОП просить встановити часову
позначку

13

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

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

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

Таким чином, ви можете зробити висновок про точний час UTC таким чином.

Коли ви хочете повернути значення Date назад на сервер, який ви б зателефонували

someDate.toISOString();

або якщо ви бажаєте працювати з мільюсекундною міткою часу (кількість мілісекунд з 1 січня 1970 UTC)

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, DateTime = 8/26/2014 18:36:40, дата = 8/26/2014, час = 6: 36: 40


1
Додаючи getTimezoneOffsetзначення у своїй getCurrentTimeUTCфункції, ви фактично повертаєте інший момент часу. Результатом getTimeє вже в UTC.
Метт Джонсон-Пінт

1
@MattJohnson: Це неправильно. Результатом tmLoc.getTime()є компенсування місцевого часу. Це легко перевірити, чи є у вас доступ до всього, що працює на JavaScript.
ahmd0

2
Вибачте, але це неправда. Див. Посилання на MDN . Це також можна побачити в специфікації ECMAScript. § 15.9.3.3 описуєgetTime , що вказує на "значення часу", визначене в § 15.9.5 , що є a 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

Ще одна неправильна відповідь, getTime повертає зміщення UTC, додаючи локальне зміщення часового поясу повністю його збиває з ладу. Зсуви ECMAScript є + ve для заходу та -ve для сходу, тому їх слід відняти від UTC, щоб отримати локальний. Але оскільки значення часу почне з UTC, додавання по суті зміщує його від UTC у зворотному напрямку до локального зміщення.
RobG

4

Якщо вам потрібен один вкладиш , тимчасову позначку UTC Unix можна створити в JavaScript як:

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

Це враховуватиме часовий пояс системи. Це в основному час, що минув в секундах з епохи.

Як це працює:

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

7
це tilde, не tilda(sic). На жаль, це не дозволить мені видалити помилку друку, я повинен зробити щонайменше 6 правок. Гладка, Stackexchange, гладка
Фред

3
Не використовуйте це . З поточною специфікацією ecma, побітові операції (як тильда - бітовий не) обробляють підписані цілочисельні значення 32 біт. Це означає, що ця магія тильди не буде працювати після 19 січня 2038 року, коли значення часової позначки буде перевищувати максимальне значення 32-бітного цілого числа, підписаного. jsfiddle.net/phb20ymb
Шаркі

3

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

Іншими словами, не переймайтеся всіма функціями JavaScript JavaScript. Замість цього просто використовуйте Date.getTime ().

Більше інформації про пояснення тут: Якщо javascript "(нова дата ()). GetTime ()" запускається з двох різних часових поясів.


3

Я використовую наступне:

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

Після визначення цього методу ви можете:

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

Найчистіший розчин. ДЯКУЮ!
лавина1

Але це не є чистим рішенням для надсилання дат, оскільки TimeStamps завжди є UTC. Найкращим рішенням для мене при надсиланні дат є використання рядкового представлення на зразок "dd / MM / yyyy HH: mm: ss", а потім проаналізувати його на стороні сервера з тимчасовою зоною за замовчуванням на сервері, щоб отримати часову позначку UTC або будь-яку іншу. Дивіться цю відповідь
jlbofh

2
розбір рядка - ви називаєте це чистим? meh
лавина1

Будьте впевнені, існують методи генерування дати у строковому форматі відповідно до специфікацій ISO. Метод - toISOString (). Ви можете чисто проаналізувати його на 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/


2

Оскільки new Date().toUTCString()повертає рядок, як "Wed, 11 Oct 2017 09:24:41 GMT"ви можете нарізати останні три символи та передати нарізаний рядок 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

РЕДАКТУВАННЯ: Код нижче НЕ працює. Я завжди припускав, що нова дата (). 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 getters, а потім нарешті зателефонувати getTime () для цього ...

Merc.


1
Ви бачили оновлення @ DCoder до його відповіді? Ваш метод getUTCUnixTimeотримує неправильний час, і JavaScript робить забезпечує простий спосіб отримати мітку часу Unix від Dateоб'єкта - з допомогою getTimeметоду. Дивіться всі інші відповіді.
Анураг

1
Фу, ти маєш рацію, щойно їх побачив. (Удар головою об стіну)
Мерк

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


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

Ви отримуєте часову позначку UNIX UTC без мілісекунд.


-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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.