Момент JS, как игнорировать часовой пояс пользователя и использовать - PullRequest
0 голосов
/ 09 января 2020

Вот сценарий:

1 - Пользователь открывает веб-сайт и вводит его в 07:00, используя раскрывающееся поле, которое даст мне следующее:

// 1578600000000 => Сохранить в DB // Пт 10 января 2020 07:00:00 GMT + 1100 (по восточному летнему времени Австралии)

Сам пользователь находится в Сиднее , что означает, что его локальные часы включены GMT+1100

Однако он хочет представить это время как время Азии / Тегерана, потому что именно там он будет завтра. По сути, он хочет, чтобы я полностью игнорировал его местное время и видел его, как будто он в Азии / Тегеране. Поэтому, когда он завтра в Tehran, он может видеть, что в его календаре есть 07:00am.

С другой стороны, люди во всем мире, которые будут видеть его доступное время, скажем, с Australia/Perth .

Я думал, что что-то похожее на приведенную ниже работу, согласно документации momentJS, но это не так.

Сначала преобразуйте часовой пояс в Asia/Tehran, который является желаемым местом пользователя :

const desiredTimeZone = 'Asia/Tehran';
let OriginalDesired = moment.tz(1578600000000,desiredTimeZone);

Затем, представляя его людям в Australia/Perth, убедитесь, что он находится в их часовом поясе

const PerthTimeZone = 'Australia/Perth`; // this is dynamic, can be anything

OriginalDesired.clone().tz(PerthTimeZone);

Я наивно думал, что это должно сработать. Но я заметил, что оригинальная отметка времени 1578600000000 - это отметка времени UTC, то есть на самом деле она не 07:00am, а на самом деле 20:00pm, потому что Javascript
вычла 11 часов, что является очень оригинальным пользователем Смещение локального часового пояса от пользовательской записи.

Мне удалось обойти его, сложив и вычтя смещение драматическим c способом, но оно работает только в одном сценарии.

const originalTime = 1578600000000;
const LocalAdjustment = moment(originalTime).tz("Australia/Sydney").utcOffset() * 60000;

const DesiredAdjustment = moment(originalTime).tz("Asia/Tehran").utcOffset() * 60000;
const newUTC = originalTime + LocalAdjustment - DesiredAdjustment;

И при представлении этого пользователю в Tehran

  moment(newUTC).tz("Asia/Tehran").format('hh:mma'); // 07:00am.

Я знаю, что это, вероятно, глупо и, очевидно, работает только в одном сценарии, но это правильный путь, который я иду ? или есть более простой способ?

Кстати, все расчеты на моем сервере, который 'UT C'.

1 Ответ

1 голос
/ 10 января 2020

Вы сказали:

1 - Пользователь открывает веб-сайт и входит в 07:00, используя раскрывающееся поле, которое даст мне следующее: // 1578600000000 ...

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

Другими словами, у вас, вероятно, есть что-то вроде:

moment("2020-01-10 07:00")

Вместо у вас должно быть что-то вроде:

moment.tz("2020-01-10 07:00", "Asia/Tehran")

Или, скорее, вы должны просто отправить "2020-01-10 07:00" и "Asia/Tehran" в вашу базу данных, а затем извлечь их и передать их в момент-часовой пояс, когда вам нужно знать, что момент, который представляет.

Что касается вашего другого подхода, обычно не стоит добавлять или вычитать смещения часовых поясов из временных отметок. Unix метки времени по своей сути основаны на UT C. Сложение или вычитание приведет к другому моменту времени, а не к часовому поясу. (Для юмористической визуализации этой логической разницы см. этот мультфильм Дилберта .)

Учтите, что существует также небольшая (но не невозможная) вероятность того, что смещения, возвращаемые вашим кодом, неверны, поскольку они должны были бы быть перемещены прежде, чем быть найденным. Другими словами, Тегеран находился в UTC + 3: 30 в указанную дату, поэтому пройденная метка времени должна быть скорректирована за 3 часа 3 минуты до передачи конструктору моментов. Это приводит к круговой логике c, и ее трудно решить. Он будет отображаться для временных отметок вблизи переходов (либо для летнего времени, либо для изменений стандартного времени для определенного часового пояса).

...