Использование timezones с moment.js fromNow() или from()

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

Дата + время действия происходит на сервере, в часовом поясе сервера. То, что вызывает проблемы, поскольку, если часовой пояс пользовательского компьютера на 12 часов превышает часовой пояс сервера, тогда, если пользователь добавит что-то прямо сейчас, moment.js покажет "12 часов назад" в качестве вывода fromNow(), а не just now.

Чтобы попытаться решить эту проблему, я пытаюсь выполнить следующий метод:

var actionTime = moment( action.timeStamp);//time of when user performed action 
var serverTime = moment().zone('-07:00'); //current server time

console.debug( serverTime);//outputs Wed Sep 11 2013 15:19:51 GMT-0700

var timeAgo = serverTime.from( actionTime);

Но несмотря на все это, timeAgo все еще показывает разницу между часовым поясом клиента и часовым поясом сервера (т.е. показывается "12 часов назад" вместо "сейчас" );

Кто-нибудь знает, как исправить это или что я делаю неправильно?

Ответ 1

В идеале вы хотите передать временную метку UTC с вашего сервера клиенту. Это не означает, что вам нужно переключить весь сервер на UTC, это просто означает, что вы конвертируете с момента времени в вашей базе данных в UTC на сервере, прежде чем отправлять его через Интернет. Конечно, было бы даже лучше, если бы вы на самом деле хранили время в UTC, но вы сказали, что сейчас не в состоянии сделать такое изменение. Но позвольте просто исходить из предположения, что вы вообще ничего не можете изменить на сервере.

Мы также предположим, что ваш сервер привязан к смещению UTC-07: 00. В реальной жизни это было бы справедливо только для таких мест, как Аризона, которые не соблюдают летнее время. Итак, если вы находитесь в Лос-Анджелесе и находитесь в Pacific Time, то некоторые ваши данные основаны на UTC-07: 00, но некоторые из них основаны на UTC-08: 00. Для этого требуется гораздо больше работы, если вы хотите сделать это в JavaScript.

Предположим также, что ввод уже является строкой в ​​формате ISO8601. (Если это не так, дайте мне знать, и я настрою этот код.)

var s = "2013-09-11 18:00:00";  // from action.timeStamp

var actionTime = moment(s + "-07:00", "YYYY-MM-DD HH:mm:ssZ");

var timeAgo = actionTime.fromNow();

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

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

Ответ 2

Я решил это по-другому, возможно, этот вариант не был возможен, когда вопрос был задан, но теперь может быть проще.

Я использовал moment-timezone.js (для чего требуется moment.js 2.6.0 +).

Я установил часовой пояс по умолчанию для моего часового пояса сервера следующим образом:

moment.tz.setDefault("America/New_York"); // "America/New_York" in my case

а затем просто используйте его нормально. fromNow() будет использовать часовой пояс в клиенте для вычисления времени, прошедшего с этого момента.

moment(myDatetime).fromNow();

Ответ 3

У меня была такая же проблема, и я использовал приведенные выше комментарии для изменения моего кода. Я решил сделать следующее:

  transform(value: string) {
    var time = moment(value).utc();
    return moment(time, "YYYYMMDD").fromNow();
  }

Мне не хватает .utc(), чтобы преобразовать его, прежде чем я применил .fromNow()

Следует отметить, что это используется в трубке для Ionic 3, а приведенный выше код - из логики трубы.