Відформатувати дату у певному часовому поясі


177

Я використовую Moment.js для розбору та форматування дат у своєму веб-додатку. Як частина об'єкта JSON, мій сервер резервного сервера надсилає дати у кількості мілісекунд від епохи UTC (зміщення Unix).

Дати розбору в конкретному часовому поясі прості - просто додайте ідентифікатор часового поясу RFC 822 до кінця рядка перед розбором:

// response varies according to your timezone
const m1 = moment('3/11/2012 13:00').utc().format("MM/DD HH:mm")

// problem solved, always "03/11 17:00"
const m2 = moment('3/11/2012 13:00 -0400').utc().format("MM/DD HH:mm")

console.log({ m1, m2 })
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

Але як я відформатую дату у визначеному часовому поясі ?

Я хочу відповідати результатам незалежно від поточного часу браузера, але я не хочу відображати дати в UTC.


2
Момент ще не підтримує це, але вони над цим працюють. github.com/timrwood/moment/pull/671
Бен

5
Це має просто працювати. Якщо ви передаєте момент часового рядка, який включає бажаний зсув, він повинен зберігати це зміщення і відображати місцевий час як заданий, а не автоматично підлаштовуватися під локальний час браузера. Якби я хотів, щоб він налаштовувався на місцевий час у браузері, я б дав йому час UTC, а не явно давав би зрушення у використанні. Я маю на увазі ... Я даю це явне зміщення, чому в основному це з'їдає і робить це власне перетворення на компенсацію браузерів. Страшний дизайн.
Трайнко

@Triynko компенсує економію денного світла, тому це не завжди працює так, як очікувалося.
pinkpanther

1
Щось із цим, я хочу надрукувати час у певному форматі, наприклад, 15 березня 2018 року, але не можу знайти рядок формату для цього. Загальне DD MMM, YYYYне працює, коли я ним користуюся moment.tz("2018-02-15T14:20:00.000+0530", "Asia/Bangkok").format("DD MMM, YYYY"). Чи може хтось вказати мені в документації, де я можу знайти всі ключі для форматування часу при використанні цього api.
pRmdk

@PramodKumar Що не так? Це дає "15 Feb, 2018". Ви мали на увазі використовувати рядок формату DD MMMM, YYYYдля отримання "15 February, 2018"?
тихість

Відповіді:


248

Як вказувалося у відповіді Манту , .utcOffset()кращим методом станом на Момент 2.9.0. Ця функція використовує реальне зміщення від UTC, а не зворотне зміщення (наприклад, -240 для Нью-Йорка під час DST). Зміщені рядки типу "+0400" працюють так само, як і раніше:

// always "2013-05-23 00:55"
moment(1369266934311).utcOffset(60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).utcOffset('+0100').format('YYYY-MM-DD HH:mm')

Старший .zone()як сетер був застарілий у Moment.js 2.9.0. Він прийняв рядок, що містить ідентифікатор часового поясу (наприклад, "-0400" або "-04: 00" на -4 години) або число, що представляє хвилини позаду UTC (наприклад, 240 для Нью-Йорка під час DST).

// always "2013-05-23 00:55"
moment(1369266934311).zone(-60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).zone('+0100').format('YYYY-MM-DD HH:mm')

Для роботи з названими часовими поясами замість числових зміщень включайте момент часу часового поясу та використовуйте .tz()натомість:

// determines the correct offset for America/Phoenix at the given moment
// always "2013-05-22 16:55"
moment(1369266934311).tz('America/Phoenix').format('YYYY-MM-DD HH:mm')

У мене виникли проблеми з цим через помилку "TypeError: Об'єкт 240 не має помилки" формат "методу. Я зрозумів, що зона доступна лише як сеттер на версії 2.1.0 і вище Moment.js (і я була на більш старій версії). Дякую!
Мелінда

5
@ebi За замовчуванням він уже використовує часовий пояс браузера. Щоб отримати доступ до зміщення часового поясу браузера, використовуйте .zone()як геттер, який повертає хвилини з UTC (наприклад, повертає 300 для Нью-Йорка за стандартний час).
тихість

1
@EricCope Ні, не зовсім. Однак ви можете використовувати, .tz("America/Phoenix")якщо ви також включаєте momentjs.com/timezone . Я оновив відповідь прикладом.
тихість

1
Зауважте, що використання зсуву не буде працювати, як очікувалося, якщо часовий пояс відрізняється зміщенням через економію денного світла.
pinkpanther

1
Чи .utcOffset () автоматично керує літнім часом? наприклад, коли я встановлю UTC +1 CET взимку, чи буде ставити UTC +2 CEST в літній час? Тому що це робить його корисним чи ні!
haemse

61

Використовуйте момент-часовий пояс

moment(date).tz('Europe/Berlin').format(format)

Перш ніж мати можливість отримати доступ до певного часового поясу, вам потрібно буде завантажити його так (або використовувати альтернативні методи, описані тут )

moment.tz.add('Europe/Berlin|CET CEST CEMT|-10 -20 -30')

Я не думаю, що момент tz був доступний, коли питання було задано, але я думаю, що це може бути шлях. В даний час я працюю над подібною проблемою з усіма часовими позначками, що зберігаються як UTC в MySQL, але для перегляду в певній зоні, залежно від конфігурації користувача, а не часового поясу клієнта.
nickdnk

47

У парі відповідей уже згадується, що момент-часовий пояс - це шлях, який слід назвати часовим поясом. Я просто хочу уточнити щось про цю бібліотеку, що мене дуже заплутало. Існує різниця між цими двома твердженнями:

moment.tz(date, format, timezone)

moment(date, format).tz(timezone)

Якщо припустити, що часовий пояс не вказаний у даті, переданій у:

Перший код приймає дату і передбачає, що часовий пояс є тим, що передано. Другий буде приймати дату, припускати часовий пояс у браузера, а потім змінювати час та часовий пояс відповідно до переданого часового поясу.

Приклад:

moment.tz('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss', 'UTC').format() // "2018-07-17T19:00:00Z"

moment('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss').tz('UTC').format() // "2018-07-18T00:00:00Z"

Мій часовий пояс становить +5 від utc. Тож у першому випадку це не змінюється, і він встановлює дату та час, щоб мати часовий пояс utc.

У другому випадку він припускає, що дата, передана, знаходиться в -5, потім перетворює її в UTC, і тому вона виписує дату "2018-07-18T00: 00: 00Z"

ПРИМІТКА: Параметр формату дійсно важливий. Якщо пропущений момент може повернутися до класу Дата, що може непередбачувано поведінку


Якщо припустити, що часовий пояс задається в дату, передану в:

У цьому випадку вони обидва поводяться однаково


Незважаючи на те, що зараз я розумію, чому це працює саме так, я подумав, що це досить заплутана особливість і варто пояснити.


1
момент (...). tz не є функцією
K - Токсичність в SO зростає.

5
Ви встановили момент-часовий пояс?
Нікола Педретті

чи є спосіб повернути проаналізований та перетворений момент назад без форматування? Наприклад, якщо я хочу форматувати різні способи, не розбираючи їх знову.
jEremyB

Дякую за роз’яснення цього. У мене виникли проблеми при встановленні іншого часового поясу, ніж часовий пояс браузера користувача, і це була саме проблема.
Робін Шааф

20

.zone () застарілий, і замість цього слід використовувати utcOffset:

// for a timezone that is +7 UTC hours
moment(1369266934311).utcOffset(420).format('YYYY-MM-DD HH:mm')

8

У мене виникли ті ж проблеми з Moment.js. Я встановив момент-часовий пояс, але проблему не було вирішено. Потім я зробив лише те, що тут виставлено, встановив часовий пояс, і це працює як шарм:

moment(new Date({your_date})).zone("+08:00")

Дуже дякую!


16
Не слід використовувати new Date()конструктор. Момент надає все, що вам знадобиться для розбору дат. Див PARSING документи.
тихий хвірт

Так, але якщо я цього не роблю, я отримую попередження від Моменту, що воно застаріло у чомусь подібному
facundofarias

7
Попередження означає, що "Момент" внутрішньо повертається до того, що ви робите (використовуючи new Date()внутрішньо), але це непослідовно у веб-переглядачах . Натомість слід використовувати наданий очікуваний формат як другий аргумент. Приклад: moment("12-25-1995", "MM-DD-YYYY").
тихий хвірт

4

Щойно я прийшов до цього безвізу, і оскільки у мене був той самий випуск, я б просто опублікував результати, які я придумав

під час розбору ви можете оновити зміщення (тобто я розбираю дані (1.1.2014), і я хочу лише дати, 1 січня 2014 року. На GMT + 1 я отримаю 31.12.2013. Тому я спочатку змістив значення.

moment(moment.utc('1.1.2014').format());

Ну, мені було в нагоді підтримка в часових поясах

Б


-7

Ви можете спробувати це,

Тут ви можете отримати дату на основі часового поясу клієнта (браузера).

moment(new Date().getTime()).zone(new Date().toString().match(/([-\+][0-9]+)\s/)[1]).format('YYYY-MM-DD HH:mm:ss')

Згенетика в основному отримує значення зміщення.

Ура !!


Зазвичай момент дає вам все необхідне. Вам ніколи не потрібно відповідати чомусь звичайному.
Махеш Самудра
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.