LINUX.ORG.RU

Как синхронизировать таймзону между фронтендом и бэкендом?

 ,


0

3

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

Мой вопрос относится к API для фронтенда (т.е. речь идет не про RESTful API для server-to-server взаимодействия, а про API для фронтендов к которому одно из приоритетных требований - это минимизация количества запросов).

Например, есть метод который должен выдать список задач на сегодня. Понятие «сегодня» зависит от текущей таймзоны. Как бэкенду определить текущую таймзону фронтенда? Мои варианты:

  1. Посмотреть в профиле пользователя, какая там указана таймзона. С профилем есть две проблемы: во-первых, пользователи очень редко выбирают свою таймзону, во-вторых, даже если пользователь указал правильную таймзону в профиле (или, например, её удалось как-то автоматически определить при регистрации), пользователь может поехать (или вообще переехать) в другой часовой пояс.

  2. В метод списка задач на сегодня нужно явно передать таймзону, что-то вроде: GET /tasks/today?offset=+03:00 ИМХО выглядит как какой-то костыль.

  3. Добавить ко всем запросам в API заголовок что-то вроде Current-User-Offset: +03:00 Если заголовок не передан, ориентироваться на значение по умолчанию (например, на таймзону из профиля).

  4. API спроектирован неправильно, таких проблем быть вообще не должно. Например, нужен метод с получением списка задач, а какие из задач отнести к «сегодняшним» решает фронтенд.

★★

пользователь может поехать (или вообще переехать) в другой часовой пояс.

А может поехать в отпуск и ожидать, что список задач будет в старой таймзоне. Гуглекалендарь в этом случае спрашивает, сменить ли таймзону на текущую браузерную.

x3al ★★★★★
()

Что касается собственно задачи. Он когда ее ставил, что он имел в виду? В шесть часов выпить кефир, как врач сказал. В шесть часов позвонить Ивану, как он просил. Если он поехал в соседний регион, где сдвинуто время, об обоих событиях ты одновременно оповестишь?

asdpm
()
Ответ на: комментарий от asdpm

Задача здесь абстрактна, просто как пример.

Например, есть план тренировок, нужно делать пробежку каждый день в 19:00. Очевидно что, если речь идет о каком-то кардинальном изменении таймзоны, приложение не должно предложить сделать пробежку в три часа ночи.

SaBo ★★
() автор топика
Ответ на: комментарий от SaBo

А, я понял проблему. Я бы сделал так: клиент определяет начало и конец своего дня в UTC и говорит серверу «дай мне задачи между этими двумя таймстэмпами». Вторую дату можно заменить на продолжительность (24 часа) или вовсе убрать, если продолжительность строго фиксирована.

filosofia
()
Ответ на: комментарий от SaBo

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

вар2: сменить дату в запросе (дата весьма относительное геопривязанное понятие) на точный запрос «дай мне задачи которые надо выполнить в ближние сутки» и все проблемы снимаются как бессмысленные, если есть важные задачи в ближние 24 часа, то они есть вне зависмости от часовых поясов и текущего времени работы - меня и ногда и ночнует пропирает поработать а днем балду попинать. самым эффективным ентое будет для задачника команды, работающих одновременно в разных часовых поясах.

эт так мысли фслух

pfg ★★★★★
()
Ответ на: комментарий от SaBo

Задача здесь абстрактна, просто как пример.

Судя по твоему описанию, в задачах указания на tz нет, они выражены как бы в localtime, но как бы и нет. Я имею в виду, что при переезде одни задачи меняют положение абсолютное, а другие - нет.

Но вообще, пользователь, он сам как воспринимает это? Если он переехал, он переводит часы? Или часы сами узнали, что он переехал и перевелись?

пробежку каждый день в 19:00 А как пользователь понимает, что сейчас 19:00?

Если задачи у тебя выражены по «как бы localtime» (я выше говорил, в чем там нюанс), то надо сообщить серверу свою таймзону. А заголовком, параметром или отдельным методом - да какая разница.

Отдельная проблема, если его TZ меняется, как вы будете это выявлять на клиенте автоматически, допустимо ли его беспокоить этими вопросами, доверять его системе и пр.

asdpm
()

Взять текущее клиентское время, скопировать в 2 переменных у первой установить время 0:00:00 у второй 23:59:59. От обоих получить unixtime и передать в запросе как параметры from и to

cobold ★★★★★
()
Ответ на: комментарий от asdpm

Можно рассмотреть такой вариант («но это не точно»): переместить проблему на клиент, то есть принимать запросы на выборку только с указанием offset (именно offset а не timezone abbreviation). А клиент, когда заметит, что в операционке оно сменилось, продолжит брать ее из операционки, но покажет предупреждающую надпись.

asdpm
()
Ответ на: комментарий от asdpm

«покажет предупреждающую надпись» я видел ввиду по смыслу что, «кажется ваш компьютер считает, что он переехал. если это только ваш компьютер переехал, но не вы сами, пожалуйста смените на клиенте настройку с Automaic (System), на конкретный offset или TZ». А серверу-то всё равно как клиент этот offset добывает для каждого запроса.

asdpm
()
Ответ на: комментарий от slovazap

Общение с бэкендом только в unix timestamp, на фронте оно конвертится в локальную таймзону пользователя

Он же под 4 предлагает передать список задач на клиента и клиент сам фильтрует. У него задачи, насколько я понял, хранятся без информации о смещении. Как он дату-время в задаче переведет в unix timestamp? Да и смысл использовать при транспортировке unix timestamp вместо нормальных форматов малопонятен.

asdpm
()
Ответ на: комментарий от asdpm

Он же под 4 предлагает передать список задач на клиента и клиент сам фильтрует. У него задачи, насколько я понял, хранятся без информации о смещении. Как он дату-время в задаче переведет в unix timestamp?

В чём проблема?

> a = new Date()
Date Wed Sep 07 2022 18:37:22 GMT+0300 (Moscow Standard Time)
> a.getTime()
1662565042905
> b = new Date(1662565042905)
Date Wed Sep 07 2022 18:37:22 GMT+0300 (Moscow Standard Time)

Это unix timestamp c миллисекундами.

Да и смысл использовать при транспортировке unix timestamp вместо нормальных форматов малопонятен.

Ну-ка, ну-ка, расскажи же скорее, какие же это такие нормальные форматы.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

В чём проблема?

У него задачи, насколько я понял, хранятся без информации о смещении. То есть в неизвестном localtime, которое кроме прочего еще и меняется.

Unix timestamp, ЕМНИП, по-определению UTC, т.е. это метка времени конкретно по Гринвичу. Проще говоря, любой unix timestamp - он +0000, z.

на фронте оно конвертится в локальную таймзону пользователя

Информацию о смещении ты предлагаешь оставить на клиенте.

Общение с бэкендом только в unix timestamp

Чтобы эти записи при отгрузке клиенту представить, как ты предлагаешь, в unix timestamp, нужно, таким образом, timestamp в неизвестном localtime преобразовать в timezone-aware (timestamptz) без знания смещения, что невозможно в принципе.

Да и смысл использовать при транспортировке unix timestamp вместо нормальных форматов малопонятен

Ну-ка, ну-ка, расскажи же скорее, какие же это такие нормальные форматы.

Ну-ка, ну-ка, пойди почитай про iso8601.

asdpm
()

Вариант 1 с полуавтоматическим обновлением профиля, если фронт увидел разночтения.

Или в базе хранить не таймстамп, а дата-время как есть.

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

vbr ★★★
()
Последнее исправление: vbr (всего исправлений: 3)
Ответ на: комментарий от SaBo

Например, нужно уйти на пробежку в 19:00 по локальному времени.

Это в принципе не работает, если события отслеживаются на сервере. Сервер может не знать что пользователь умотал в другую таймзону.

не должно предложить сделать пробежку в три часа ночи

Если пользователь дундук и «не перевёл часы» то это его проблемы.

no-such-file ★★★★★
()

В метод списка задач на сегодня нужно явно передать таймзону, что-то вроде: GET /tasks/today?offset=+03:00 ИМХО выглядит как какой-то костыль.

/tasks?date=2022-09-07&offset=-180

В JS

var d = new Date();
let offset = d.getTimezoneOffset(); // -180
let isoDate = d.toISOString().substring(0, 10); // 2022-09-07
thegoldone
()
Ответ на: комментарий от asdpm

У него задачи, насколько я понял, хранятся без информации о смещении. То есть в неизвестном localtime, которое кроме прочего еще и меняется

localtime можно перевести в unix time в локальной таймзоне сервера, равно как и наоборот.

Unix timestamp, ЕМНИП, по-определению UTC, т.е. это метка времени конкретно по Гринвичу. Проще говоря, любой unix timestamp - он +0000, z.

Нет, unix timestamp не UTC, к нему понятие тайм зоны не применимо. Это просто количество секунд.

Информацию о смещении ты предлагаешь оставить на клиенте.

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

Чтобы эти записи при отгрузке клиенту представить, как ты предлагаешь, в unix timestamp, нужно, таким образом, timestamp в неизвестном localtime преобразовать в timezone-aware (timestamptz) без знания смещения, что невозможно в принципе.

Если даты сгенерированы на сервере, у них известна таймзона (в предположении что сервер не перемещался). Если даты пришли с клиента, при этом их таймзона неизвестна, то ничего уже не поделаешь - информация потеряна. Надо сделать правильно и смириться с тем что задания созданные до сего времени могут быть смещены на сутки в любую сторону.

Ну-ка, ну-ка, пойди почитай про iso8601.

Извини, но не тебе, с представлением о работе со временем на уровне ЕМНИП, отсылать меня базовые вещи читать. И, кстати, прекрати употреблять слово «смещение». Таймзона - это не (только) смещение, это информация о том как это смещение менялось в прошлом и, в определённых пределах, будет меняться в будущем. 12:00MSK и 12:00+0300 сегодня может совпадать, когда-то не совпадало, и когда-то может различаться вновь.

Кстати, я тут понял что ТС даже не сказал к какому времени у него привязаны задания, а я, в силу специфики собственной работы, предположил что времена абсолютны. На самом деле есть масса вариантов:

  • абсолютные времена (UTC, или «через 48 часов с текущего момента»)
  • времена в локальной таймзоне (в 10:00 я завтракаю)
  • времена в фиксированной таймзоне (в 12:00 у меня zoom с Петей из Москвы (по его времени))

Для 2 варианта нужно хранить и передавать отдельно время и, возможно, дату, для 3 варианта ещё и таймзону (не «смещение»). Для 2 и 3 варианта действительно подойдёт iso8601 без указания смещения (а таймзон оно не умеет, поэтому и говно, при этом и для абсолютных времён избыточно и неудобно, в частности потому что позволяет разные представления одного и того же момента времени, то есть всегда требует парсинга в число).

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Нет, unix timestamp не UTC, к нему понятие тайм зоны не применимо. Это просто количество секунд.

Посмеялся над тобой. А еще умничаешь...

Ты, видимо, вообще слабо себе представляешь, что такое метки времени и таймзоны.

1) В одном из предыдущих сообщений ты приводишь вариант, в котором значение о смещении localtime относительно UTC находится на клиенте (и это правильно, и это вытекает из задачи топикстартера).

2) В обмене ты предлагаешь unixtime, а это time instant выраженный по UTC. Фактическое смещение клиента здесь теряет значимость, не передается, т.к. смещение в timestamptz не говорит о том, что клиент именно в этой таймзоне, а только о том, что он пожелал выразить time instant с таким смещением. То есть опять же подтверждается, что в предложенном тобой варианте информация о фактическом смещении клиента на сервере отсутствует.

localtime можно перевести в unix time в локальной таймзоне сервера

3) Мои разъяснения из прошлого сообщения идут тебе на пользу. Ты теперь понял, что преобразовать «naive» метку в «aware» без знания о смещении нельзя - это нонсенс. И до тебя даже дошло, раз смещение всё-таки нужнО, то оно возьмется из системы. И ты даже сам озвучил с какой. Но есть проблема проблема: это серверное смещение не имеет отношения к динамической таймзоне потребителя (из задачи топикстартера). То есть такое допущение («потребитель всегда переместился в место, где смещение как у нас сервере») - оно в принципе ошибочно.

Такая вот каша у тебя в голове.

Извини, но не тебе, с представлением о работе со временем на уровне ЕМНИП, отсылать меня базовые вещи читать.

Послушай-ка. Судя по всему, так получается, что даже моё «ЕМНИП», точнее и _весомей_ любых твоих попыток поумничать.

Ты демонстрируешь безграмотность и самоуверенность. Вот то, что ты сказал, оно на 100% именно тебе применимо.

asdpm
()
Ответ на: комментарий от slovazap

прекрати употреблять слово «смещение». Таймзона - это не (только) смещение, это информация о том как это смещение менялось в прошлом и, в определённых пределах, будет меняться в будущем

И, кстати, прекрати умничать. «Смещение» я употребляю, когда хочу подчеркнуть, что имею в виду именно смещение, а не таймзону. Потому, что именно смещение и нужно использовать в том контексте, в котором я это употребил. И вообще, везде, где это возможно, нужно стараться таймзоне предпочесть смещение.

asdpm
()
Ответ на: комментарий от asdpm

В обмене ты предлагаешь unixtime, а это time instant выраженный по UTC. Фактическое смещение клиента здесь теряет значимость, не передается, т.к. смещение в timestamptz не говорит о том, что клиент именно в этой таймзоне, а только о том, что он пожелал выразить time instant с таким смещением. То есть опять же подтверждается, что в предложенном тобой варианте информация о фактическом смещении клиента на сервере отсутствует.

Это набор слов, в котором, исходя из твоих хамских пассажей про «безграмотность и самоуверенность», ты со мной споришь, но даже не пишешь с чем не согласен. Расцениваю это как попытку сохранить лицо сев в лужу, и даю последний шанс оправдаться.

  • Если события привязаны к абсолютному времени, то никаких смещений передаваться не должно, должно передаваться только абсолютное время в виде unix timestamp. Информация о смещении нужна только на клиенте чтобы отобразить timestamp как локальное время или из локального времени получить timestamp. Для выборки событий «на сегодня» нужно передать на сервер два timestamp сконвертированные на клиенте для локальных 00:00 и 23:59.
  • Если события привязаны к локальной таймзоне клиента, нужно передавать и хранить только дату и время без какой либо таймзоны. Для выборки событий «на сегодня» нужно передать на сервер только дату.
  • Если события привязаны к конкретной таймзоне, нужно передавать и хранить время с таймзоной. Для выборки событий «на сегодня» на сервер нужно передать два timestamp как в 1 случае, на сервере их сравнивать с timestamp полученными из хранящихся времени+таймзоны.

С чем ты не согласен?

Но есть проблема проблема: это серверное смещение не имеет отношения к динамической таймзоне потребителя (из задачи топикстартера). То есть такое допущение («потребитель всегда переместился в место, где смещение как у нас сервере») - оно в принципе ошибочно.

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

И вообще, везде, где это возможно, нужно стараться таймзоне предпочесть смещение.

Ни в коем случае, и я написал почему. «Предпочесть смещение» - значит польностью игнорировать таймзоны, их изменения и DST. Время + смещение - это просто время в неудобном формате.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Вот это твоя безграмотность, самоуверенность, ЧСВ... типовой букет среднего айтишника, короче.

Мое сообщение:

Unix timestamp, ЕМНИП, по-определению UTC, т.е. это метка времени конкретно по Гринвичу. Проще говоря, любой unix timestamp - он +0000, z.

Твое сообщение:

Нет, unix timestamp не UTC, к нему понятие тайм зоны не применимо

Мое сообщение:

Посмеялся над тобой. А еще умничаешь...

Твое сообщение:

Расцениваю это как попытку сохранить лицо сев в лужу, и даю последний шанс оправдаться

То есть ты обосрался дважды. Ты совсем опозорился.

----

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

asdpm
()
Ответ на: комментарий от asdpm

Мое сообщение:

Unix timestamp, ЕМНИП, по-определению UTC, т.е. это метка времени конкретно по Гринвичу. Проще говоря, любой unix timestamp - он +0000, z. Твое сообщение: Нет, unix timestamp не UTC, к нему понятие тайм зоны не применимо

Ещё раз, у количества секунд нет никакой таймзоны, как нет его у количества раз сколько ты опозорился. Это просто число, одинаковое для любого момента времени в любой точке земного шара.

Полностью я твое сообщение не читал

Понятно, удачи.

slovazap ★★★★★
()
Ответ на: комментарий от slovazap

Ты продолжаешь позориться. Это видимо у тебя стратегия, как убедить всех, что ты не сел в лужу. Мой тебе совет: знай свое место, поумерь гонор, тогда не будешь позориться так.

asdpm
()
Ответ на: комментарий от no-such-file

Сервер может не знать что пользователь умотал в другую таймзону.

Почему? Я видел, что некоторые приложения на мобилах запрашивают текущее местоположение (не знаю уж, для определения таймзоны или для других целей). Уверен, что web-сервер тоже может по GeoIP как-нибудь зону определить, а так же сменилась она, или нет.

Shushundr ★★★
()
Ответ на: комментарий от bugfixer

Вот еще один некомпетентный «умник», неспособный разобраться с таймзонами и unixtime.

Мы вам перезвоним, bugfixer, пойдите пока азы освойте, ну или научитесь думать, ну или читать.

asdpm
()
Ответ на: комментарий от vbr

Или в базе хранить не таймстамп, а дата-время как есть.

Нельзя если события шарятся между разными юзерами (в смысле событие «созвон в зуме» между юзерами с разными таймзонами должно работать). Но имеет смысл если это, например, будильник (если он в 7:00 и летнее время существует, 7:00 летнего и зимнего времени технически в разных таймзонах, но будильник автоматически переводится). Понятно, что для однократных событий некритично.

Из моего опыта, «дата-время как есть» нужны только для повторяющихся вещей для учёта летнего времени/возможной смены таймзоны (ну в смысле глобальный перевод на час вперёд или переход города в другую таймзону). Во всех остальных случаях в базе нужно хранить tz-aware таймштамп будущего события. Даже для повторяющихся вещей чаще имеет смысл скастовать в «дату-время как есть» из tz-aware таймштампа прямо перед тем, как добавить повторений. Исключения — что-то вроде будильников, гарантированно однопользовательские события.

Ну а по теме — очевидно же, что будет таймзона в профиле (автоматически заполняется из браузера при регистрации профиля, можно менять руками) и всплывающий диалог если в браузере она поменялась.

x3al ★★★★★
()
Последнее исправление: x3al (всего исправлений: 1)
Ответ на: комментарий от SaBo

Если всё это однопользовательское, групповых событий нет а повторений (ежедневных, еженедельных и прочего) полно — лучше не использовать таймзоны. Wall-clock time в этом случае проще.

x3al ★★★★★
()
Ответ на: комментарий от SaBo

нужно делать пробежку каждый день в 19:00. Очевидно что, если речь идет о каком-то кардинальном изменении таймзоны, приложение не должно предложить сделать пробежку в три часа ночи.

Очевидно только то, что твой незадачливый пользователь теперь пропустил собеседование, лот на eBay и приём жизненно важного лекарства.

Ехать вместе с таймзоной события должны только если явно об этом просить, и это будет фичей нужной примерно никому.

t184256 ★★★★★
()
Ответ на: комментарий от bugfixer

В чем конкретно я якобы не прав?

В том, что unixtime по определению timezone-aware выраженный по UTC, т.е. подразумевает невидимый +00:00 / Z ? Кто будет это оспаривать причем так уверенно? Высокомерный профан только. Ты в компанию к slovazap присоединяешься?

Или в том, что у slovazap каша в голове и он предлагает совершеннейшую чушь топикстартеру? Или в том, что транспортировать метки именно как unixtime - это бред при наличии нормальных форматов iso8601?

asdpm
()
Ответ на: комментарий от bugfixer

Ирония в том, что slovazap со своим unixtime обосрался именно в том аспекте, с которым iso8601 с явным указанием смещения успешно борется. А именно: с неявными смещениями в передаваемых значениях! То есть высокомерный упертый неуч не знает, что unixtime по UTC, а iso8601 с явным смещением призвано неуча спасти. Но высокомерие и упертость авторы стандарта победить не могут.

То есть iso8601 с явным смещением оно foolproof, но всё-таки иногда не foolproof. Что хорошо нам показал безграмотный топящий за unixtime slovazap. (И видимо bugfixer).

asdpm
()
Ответ на: комментарий от bugfixer

Ты под этим его сообщением тоже подпишешься?

Нет, unix timestamp не UTC, к нему понятие тайм зоны не применимо. Это просто количество секунд.

Да или нет?

Или ты тоже профнепригодный клоун, но всё немного другой?

asdpm
()
Ответ на: комментарий от asdpm

Это просто количество секунд.

Да или нет?

Да, подпишусь.

Или ты тоже профнепригодный клоун, но всё немного другой?

Попкорном запасся. Не останавливайтесь, пожалуйста.

bugfixer ★★★★
()
Ответ на: комментарий от bugfixer

Я сначала было подумал, что ты просто не уловил суть обсуждения, не читал всех сообщений моих внимательно, ну и решил просто топить за свои тупые 4 байта unixtime для передачи по HTTP вместо iso8601 с указанием смещения. Дескать «экономия же» (ну или какие там еще у тебя могут быть доводы в пользу этого инта тупого это уж тебе виднее).

Но теперь ясно, что с тобой дело хуже: у нас в треде еще один терминально профнепригодный, да еще и непрошибаемый.

Скажи пожалуйста, с чем ты конкретно споришь? То есть, какой твой довод? На чем ты настаиваешь? Твое утверждение? Ты сможешь его сформулировать?

asdpm
()
Ответ на: комментарий от bugfixer

Ты под этим его сообщением тоже подпишешься?

Нет, unix timestamp не UTC, к нему понятие тайм зоны не применимо. Это просто количество секунд.

Да, подпишусь.

Потрясающе.

asdpm
()
Ответ на: комментарий от Shushundr

может по GeoIP

По какому IP, клиент вообще не обращается к серверу. Поставил напоминалку и ушёл, а сервер через пуш типа должен пнуть клиента когда придёт время.

no-such-file ★★★★★
()