2016-05-01 2 views
0

Во-первых, я надеюсь, что это не дубликат. Я прочитал много подобных вопросов, но не могу найти один с этой конкретной проблемой.Компенсация за utcOffset в Moment.js

У меня есть japcript datepicker, который использует дату javascript внутри, которая имеет непреднамеренный побочный эффект. Когда я выбираю 30 апреля 2016 года, он возвращает объект даты в полночь (00:00) в эту дату, но если вы находитесь в другом часовом поясе и он использует UTC внутренне, он возвращает объект, который компенсирует смещение UTC. Итак, потому что это BST здесь, я вернусь, это 30-го апреля 00:00 GTM + 1:00, которое, когда вы превращаете его в строку ISO, на самом деле 23:00 29 апреля.

Я хочу послать правильную дату (30 апреля, нет времени) на сервер, но строку даты я в настоящее время получить при этом:

var newDate = moment(newValue).toISOString(); 
console.log(newDate); 

это:

2016-05-19T23:00:00.000Z 

Итак, мое понимание об этом слабое, но я думаю, что datepicker использует мое местное временное смещение изначально, чтобы взять час, если и хранить 23:00 19-го числа в качестве даты UTC внутри, так что это уже дата UTC, конвертируя в UTC не поможет.

Что мне нужно сделать, это использовать moment.js, чтобы компенсировать utcOffset и сдвинуть дату так, чтобы было полночь в дату, которую я выбрал в UTC.

+0

Итак, чтобы уточнить, ваш дампинг дает вам собственный объект даты JS. Значение UTC этого объекта даты - это значение, которое вы хотите, чтобы Moment интерпретировал как локальное время? –

+0

Нет, все наоборот. Почему бы не просто позвонить .format («ГГГГ-ММ-ДД») в свой момент? В приведенном выше сценарии вы получите «2016-05-20», если вы находитесь в британском летнем времени. –

+0

Он хранит дату UTC 19-го числа в 23:00. Преобразование его в iso дает мне это как строку, которую я не хочу. Тем не менее, javascript видит это как полночь 20-го, и использование .format() действительно дает мне строку, которую я хочу с 20-м, предположительно потому, что javascript видит дату как 20-е, потому что она автоматически добавляет в мое смещение. Мне показалось странным, что .toISOString() преобразует дату UTC в строку, но .format() будет форматировать локальную дату. Ваш ответ правильный, хотя, если вы выразите его как ответ, я сделаю это правильно. – jonhobbs

ответ

4

Что вы видите здесь, так это то, что объект JS Date и MomentJS содержат внутреннюю метку Unix Time в миллисекундах. Эти метки времени являются ссылкой на точку на глобальной временной шкале, которая может быть преобразована в локальное время, если это необходимо.

Когда вы используете конструктор по умолчанию moment(), вы сообщаете Moment о работе в «локальном» режиме. Это означает, что когда Moment отображает дату, которую он содержит, он будет конвертировать из штампа времени UTC Unix, который он содержит внутри, к местному времени пользователя.

Если вы хотите сохранить время UTC (что вы не делаете), вы можете передать объект JS Date, который вы получаете от своего выбора даты, до функции moment.utc(), а затем, когда вы набрали .format() в тот момент, вы всегда будет видеть время UTC.

В качестве примера я нахожусь в Центральном летнем времени Соединенных Штатов прямо сейчас, делая свое смещение -5.

Если я ваш пример UTC штамп времени и передать его в момент конструктор по умолчанию в, я получаю следующее:

moment('2016-05-19T23:00:00.000Z').format() 
"2016-05-19T18:00:00-05:00" 

Как вы можете видеть, для целей отображения, Moment преобразовал в местный часовой пояс ,

Если бы я должен был использовать UTC, хотя:

moment.utc('2016-05-19T23:00:00.000Z').format() 
"2016-05-19T23:00:00+00:00" 

Без изменений.

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

Что касается того, почему .toISOString() всегда дает вам дату UTC, когда вы вызываете его на объект JS Date, вы можете поблагодарить комитет TC39 за это.Вот как это должно работать по спецификации ES2015: http://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.toisostring

Moment также всегда предоставляет UTC для .toISOString() ради согласованности с тем, как работает родная дата.

+0

Я добавил некоторые пояснения в отношении .toISOString в документации Moment. Он должен выйти на этой неделе. –

+0

Отличный ответ, очень полный. Спасибо. – jonhobbs

+0

Ваша «отметка времени UNIX» вернее [* значение времени *] (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-time-values-and-time- ассортимент). Конструктор ECMAScript * Date * является [* встроенным * объектом] (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-built-in-object) и встроенным В конструкторе. До и включая ES5 термин «родной объект» означает то же, что и текущий ECMAScript 2015 [* стандартный объект *] (http://www.ecma-international.org/ecma-262/6.0/index.html#sec -стандартный объект) (которые также являются «обычными объектами»). Таким образом, экземпляр * moment * является стандартным объектом. – RobG

Смежные вопросы