passshift
@passshift
php, js, html5, css

Как учитывать часовой пояс при работе с Moment.js?

Здравствуйте!

Появилась проблема с временными зонами юзеров. Весь день потратил чтобы понять как работает Moment.js и почему его так нахваливают.

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

Выставляю глобальную локаль и часовой пояс:

moment.locale('ru');
moment.tz.setDefault("Europe/Moscow");


Пытаюсь вывести текущее время с учетом часового пояса:
var now = moment().format('MMMM Do YYYY, HH:mm:ss');
console.log(now) // получаю Февраль 3-го 2016, 02:36:51


Хотя должно показать Февраль 3-го 2016, 03:36:51 - это время стоит на ПК и это точное Московское время на данный момент.
При изменении времени на ПК в большую сторону (04:36:51) показывает правильно 03:36:51... и так с каждым часовым поясом.

Вероятно я что-то не понимаю, кто-нибудь может помочь разжевать?

С датами из прошлого примерно разобрался, там проще т.к. храню дату в БД в часом поясе UTC и Moment.js просто прибавляет или отнимает нужное количество часов в зависимости от установленного часового пояса:

var date = moment.utc('2016-01-05 12:00:00').format(); // Как-бы дата из прошлого
var converted = moment(date).format('MMMM Do YYYY, HH:mm:ss'); // Форматируем с учетом установленной глобальной временной зоны
console.log('было - ' + date + ', стало - ' + converted) // было - 2016-01-05 12:00:00, стало - 2016-01-05 15:00:00


- Все ли верно делаю или я не в ту сторону поехал? В последнем примере меня смущает первая строчка .utc, если не указывать этот параметр, то он добавляет к дате из прошлого +3 часа (Europe/Moscow), понятное дело это связано с установленным глобальным часовым поясом, но мне без него не обойтись т.к. дат много и нужно их подгонять , постоянно прописывать не станешь, хочется в одном месте указать.

Еще меня смутила функция определения клиентского часового пояса:

moment.tz.guess();

, которая выдает ошибку:

moment.js:209 Uncaught TypeError: Cannot read property 'join' of null
на этой строке следующий код:

abbr = abbr[0].match(/[A-Z]/g).join('');

- попытался убрать ковычки внутри Join-а, но не помогло, вероятно, что массив пуст и разделять нечего, выходит, что эта функция не смогла определить мою временную зону... я использую Google Chrome Версия 48.0.2564.97 m

Помогите пожалуйста разобраться, или подскажите альтернативный вариант плагина для работы с прошлым, будущим и настоящим с учетом временных зон?
  • Вопрос задан
  • 8945 просмотров
Решения вопроса 1
@bromzh
Drugs-driven development
Момент берёт инфу о времени и временной зоне из ОС. Если он показывает что-то неправильно, то значит у тебя неверно настроена временная зона в ОС.
Пример: я изменил tz на парижскую (+01:00), но время выставил московское. Если запросить момента время, то он выдаст то, что установлено в системе: 2016-02-03T04:08:24+01:00. Время совпадает с московским, но неверная tz. Если же насильно установить временную зону в самом моменте, то он возьмёт системное время и tz и попытается перевести в локальное время для указанной tz. Таким образом, если установить московскую tz и снова запросить текущее время, момент выдаст 2016-02-03T06:13:17+03:00. Время сдвинулось, но tz верная.
Так что у тебя скорее всего в системе стоит tz +04:00, вот час и теряется.

Ну и да, время нужно хранить в UTC, а выводить на страницу в соответствии с часовым поясом пользователя. Часовой пояс можно уточнять у самого клиента.
Узнавать сдвиг в минутах относительно UTC можно так: moment().utcOffset()
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы