Комментарии 39
Краткая формулировка задачи: каким-то образом current_date, current_time и current_timestamp должны выдавать дату-время в зависимости от настроек в аккаунте пользователя и при этом на самом сервере будет стоять московское время.
Зачем?
В БД должны храниться данные в известном часовом поясе, а при вводе/выводе они должны конвертироваться в тот часовой пояс, который нужен пользователю.
(есть случаи, когда конвертация не имеет смысла, но это тема для отдельного обсуждения)
И вы хотите в каждом месте делать доп манипуляции с датой?
Не в каждом, а в одном слое (скорее всего, в UI). Просто то, что вы описываете, выглядит как плохо спроектированная система.
Ну так и сделано, в UI и делается собственно
По вашему описанию — делается в БД. А БД — это не UI.
(я еще стесняюсь спросить, что будет, если с одной БД будут одновременно работать несколько пользователей, каждый из которых хочет свой часовой пояс)
Смысл в том что все даты в добавлениях и апдейтах делаются через эти view, а в селекте нам уже не нужна математика никакая… там уже дата записана с учетом часового пояса.
2. Если мы рассматриваем мою систему, то тут не совсем корректно сопоставление пользователи — часовые пояса. Есть компании, у которых есть сотрудники. Каждой компании выдается аккаунт и вот на этот аккаунт своя база данных и тут можно выставлять часовой пояс. Все сотрудники компании которые работают в ее аккаунте, работают с настройками компании в целом, т.е. с часовым поясом который настроен у компании.
Я подумал что UI по вашему это Update и Insert.
Нет, UI — это User Interface.
Смысл в том что все даты в добавлениях и апдейтах делаются через эти view, а в селекте нам уже не нужна математика никакая…
Ага. А теперь представьте, что вам надо посчитать продолжительность выполнения задачи, которая начата до перевода времени с летнего на зимнее, а закончена — после.
Все сотрудники компании которые работают в ее аккаунте, работают с настройками компании в целом, т.е. с часовым поясом который настроен у компании.
Как мило. У компании один склад в Калининграде, второй в Иркутске. И как время выдачи товара фиксировать будем?
У компании один склад в Калининграде, второй в Иркутске. И как время выдачи товара фиксировать будем?
Согласен, это проблема. Вы заставили меня задуматься над ней. Но она точно не решится индивидуальной постановкой UTC сотруднику. Она решится индивидуально постановкой UTC складу! Нельзя чтобы данные склада отображались в UTC сотрудника, ведь для каждого сотрудника дата-время приема или выдачи товара будет отображаться разное — чего быть не должно (оба позвонят начальнику и скажут: один что товар выдан в 10.00, другой что в 12.00 :) и кому верить?). При этом на UTC компании это тоже не должно быть завязано — оно может быть совершенно другим. Т.е. склад — это просто отдельный модуль с индивидуальным UTC у каждого склада.
Потом есть еще одна причина почему нельзя давать сотрудникам индивидуальный UTC, и он должен быть у компании. В частности у меня в системе можно помимо подразделений объединять сотрудников в группы, например в одном подразделении службы сети связи может быть группа сотрудников занимающийся телефонией, группа занимающиеся интернетом, телевидением и т.д. И можно например настроить чтобы задача с типом интернет пришла в это подразделение автоматически данной группе, и даже распределилась ее сотрудником по какому-то алгоритму. Может так быть, что в группу объединяются сотрудники из разных подразделений, но работающие над одной задачей каждый со своей стороны. Для этих групп могут ставиться задачи именно на группы со многими различными алгоритмами распределения, на группы могут формироваться графики работ (именно группы). Есть для групп SCRUM доски.
И вот представьте ситуацию, у одного сотрудника из группы стоит один UTC, а у другого другой! И какой при этом UTC отображать в графике группы в которую входят оба сотрудника? Это просто билеберда получится.
При этом я согласен с вами, что если один работает в Калининграде а второй в Иркутске… возможно надо просто глубже делать деление системы, вводит понятия офисов, где должно быть свое UTC и при этом запрещать программно объединять сотрудников из разных офисов. В общем действительно надо подумать.
Тут еще видимо есть у меня и дополнительная проблема, у меня в системе встроенный язык программирования (свой) и вся внутренняя кухня аккаунта сделана на нем, а все php-шное — это фактически интерпретатор, поэтому индивидуальный UTC на каком-то модуле должен реализовываться на уровне программирования на внутреннем языке, а не на интерпретаторе или базе данных.
Но вы действительно правы, рано или поздно вопрос разных UTC в каких-то модулях в рамках одной компании может встать и над этим надо подумать. Но так вот в лоб эта проблема не решается т.к. есть миллион дополнительных нюансов.
Пока я все таки считаю свой подход (UTC на компанию) правильным, в данной ситуации, но возможно его придется глубже модернизировать.
Спасибо за конструктивную критику. Она действительно полезна.
По поводу
А теперь представьте, что вам надо посчитать продолжительность выполнения задачи, которая начата до перевода времени с летнего на зимнее, а закончена — после.
Если будет необходим такой подсчет, то такой его нюанс можно реализовать программно. Момент перевода времени известен, сделать IF в процедуре, например если время перевода попадет между датами начала и конца — прибавить к продолжительности час (или вычесть — по ситуации). В общем тут я проблемы не вижу.
Вы, похоже, не понимаете, что такое UTC.
оба позвонят начальнику и скажут: один что товар выдан в 10.00, другой что в 12.00 :) и кому верить?
Никому не верить, верить системе, которая скажет, что товар выдан в 11 по времени склада.
И какой при этом UTC отображать в графике группы в которую входят оба сотрудника?
Каждому сотруднику надо отображать тот часовой пояс, который ему удобнее с точки зрения бизнеса.
Тут еще видимо есть у меня и дополнительная проблема, у меня в системе встроенный язык программирования (свой) и вся внутренняя кухня аккаунта сделана на нем, а все php-шное — это фактически интерпретатор, поэтому индивидуальный UTC на каком-то модуле должен реализовываться на уровне программирования на внутреннем языке, а не на интерпретаторе или базе данных.
Не совсем так. Корректные операции со временем, несомненно, должны быть заложены в бизнесовый язык, но при этом UI должен поддерживать отображение в том часовом поясе, в котором удобно.
Если будет необходим такой подсчет, то такой его нюанс можно реализовать программно. Момент перевода времени известен, сделать IF в процедуре, например если время перевода попадет между датами начала и конца — прибавить к продолжительности час (или вычесть — по ситуации). В общем тут я проблемы не вижу.
Вы просто никогда не пробовали это сделать, поэтому и не видите проблемы. В реальности, вам придется учитывать много нюансов и делать предположения о том, какие времена у вас записаны. А если у вас система работает со временем в известной таймзоне, вам не надо думать — вы сводите все к одной норме и считаете в ней.
Но я как бы не претендую на правильность. Я просто описал способ как это можно сделать, кому-то понравится, а кто-то придумает как сделать по своему. Но данный способ оказался наиболее простым и эффективным.
Это должно делаться (и у всех делается) в одном месте — в той или иной прослойке, которая у вас работает с БД. В большинстве бд-фреймворках/орм итд всё это есть искаропки, конечно, потому что по-другому просто нельзя.
В этом случае там будет время по МСК? Или принимать данные извне как?Пусть хоть по тихоокеанскому, время никогда нельзя передавать, обрабатывать и хранить без привязанной таймзоны (или подразумевания что там UTC, что очевидно для случая, например, типа unixtime). Нет понятия «время по МСК», время оно и есть время — просто временной штамп. По МСК оно может стать при показе его в этой таймзоне. Нет, можно и передавать его по МСК и даже хранить (только непонятно зачем), но надо тогда так и оперировать везде «01.02.2016 22:22:58; МСК», потому что нет времени «01.02.2016 22:22:58» — это не время, а билиберда.
Так же всё и про «принимать извне».
У юзера сейчас рисуется допустим 12:00 для какой-то сущности, если юзер меняет таймзону (допустим соседнюю на час) то он увидит теперь везде 13:00? Правильно же? Тогда как это делается с учётом, что в БД неизвестное время неизвестной таймзоны?
Если вы боитесь что при изменении часового пояса может получится белеберда с записями в старом часовом поясе, то во первых такие изменения делает только администратор аккаунта, во вторых это как правило разово (разве что компания решит куда-то переехать), в третих ведутся логи изменений, т.е. можно посмотреть когда было изменение часового пояса и с какого на какой и понять что откуда растет. Я в этом не вижу проблемы. Ну зачем компании больше одного раза менять часовой пояс? Они же сами себе хаос делают…
Поясните пожалуйста логику работы программы при таком случае: сегодня я в Петропавловске, а завтра в Петрозаводске. Сегодня я начал забивать отчёт, а завтра хочу его расширить новыми данными. Какое время мне инсентировать и какое я буду видеть на экране, когда вернусь в Москву?
Я не претендую на то что это единсвенно-правильный вариант, каждый его реализует все равно по своему. Статью я написал потому, что в свое время я не нашел нигде описанного способа как такое сделать и сделать это на практике у меня получилось. Может кому-то пригодиться если будет стоять похожая задача.
Статью я написал потому, что в свое время я не нашел нигде описанного способа как такое сделать
Может потому что так никто не делает?) Дело не в том, что у вас правильный или неправильный вариант реализации, вам пытаются объяснить, что сам подход неправильный, независимо от того, как он реализован. Как-то даже странно, что при проектировании системы "с огромным числом потенциальных пользователей в любом регионе" работа с временными зонами была недостаточно продумана.
Как я понял, между базой и пользователем у вас есть прослойка на PHP. Скорее всего, там есть какая-нибудь функция query(), которая выполняет запросы на чтение. Вот там после запроса можно пробегаться по полям результата и для полей datetime и timestamp делать конвертацию в таймзону пользователя. А в базе все хранить в одной фиксированной таймзоне с известным смещением (неважно, в UTC или по Москве).
В php как вы описали — делать не вариант, учитывая то, что пользователь строит сам конфигурацию, вы никогда не угадаете что это дата которую надо форматнуть (вернее угадаете, но не понятно зачем такие сложности то вообще и дополнительное процессорное время). Если так и делать то надо обрабатывать не результаты вывода query(), а в самом поле sql. Т.е. на уровне компилирования процедур на внутреннем языке. Собственно, грубо говоря, так и сделано, только через VIEW.
Почему неправильно делать именно каждому пользователю свой UTC (а надо делать компании) я описывал уже подробно «mail-online 17 декабря 2016 в 15:05» (CTRL-F сделайте)
Кстати, может кто знает, в битриксе, мегаплане, клиентской базе и т.д. есть настойка часового пояса вообще? Я например обыскал все настройки в битриксе — я не нашел… У меня есть такое подозрение, что никто не просто так не делает, а никто вообще не сделал такого в принципе.
что пользователь строит сам конфигурацию, вы никогда не угадаете что это дата которую надо форматнуть
Зачем угадывать-то, когда достаточно ввести правильный тип данных.
У меня есть такое подозрение, что никто не просто так не делает, а никто вообще не сделал такого в принципе.
Да ладно. В Jira это есть, скажем. В любом приличном современном мессенджере это есть.
(ну и в ERP-системе, в разработке которой я участвую, тоже есть, чего уж)
оба позвонят начальнику и скажут: один что товар выдан в 10.00, другой что в 12.00
Начальник компании, работающей в разных регионах, должен уточнить, в каком часовом поясе эти данные.
Представьте эту ситуацию в реальности, без использования компьютеров. Один сотрудник уехал в командировку в другой часовой пояс, ему звонит другой со склада, и говорит "товар только что прибыл". Какое время он должен начальнику сказать?
И вот представьте ситуацию, у одного сотрудника из группы стоит один UTC, а у другого другой! И какой при этом UTC отображать в графике группы в которую входят оба сотрудника?
В графике (в БД) время хранится в фиксированном часовом поясе. Каждому сотруднику он отображается в его часовом поясе. Чтобы сотрудник знал, что информация "в 12:00 мне позвонят из города N" это по его локальному времени.
вы никогда не угадаете что это дата которую надо форматнуть (вернее угадаете, но не понятно зачем такие сложности)
Насколько я понял из документации, ibase_field_info() возвращает информацию о типе поля в результате запроса. Особых сложностей тут нет, а надо все это, чтобы правильно учитывать время и правильно его отображать. Без ограничений бизнес-логики типа "и при этом запрещать программно объединять сотрудников из разных офисов".
Если так и делать то надо обрабатывать не результаты вывода query(), а в самом поле sql
Если так делать, то надо это делать в представлении при рендеринге значения со временем (заодно и формат можно задать, "d.m.Y" или "m.d.Y" или любой другой):
<td><?= $formatter->asDatetime($row['created_at']) ?></td>
У юзера сейчас рисуется допустим 12:00 для какой-то сущности, если юзер меняет таймзону (допустим соседнюю на час) то он увидит теперь везде 13:00? Правильно же?
Нет, юзер увидит 12.00 везде. В старых записях все останется по прежнему. Но новая запись будет не 12.01 а уже 13.01 в случае +1 в таймзоне.
Нет, юзер увидит 12.00 везде.Это же катастрофически неправильно. 12:00 в соседней таймзоне это не 12:00 же.
Или обратное: То есть юзер создал в 12:00 запись. Потом мгновенно переместился в соседнюю таймзону и создал запись и у вас в БД запишется две записи:
12:00
13:00
И потом он будет видеть эти два времени в таком виде из любой таймзоны? Несмотря на то, что на самом деле это одно и то же время?
Теперь более реальный случай: юзер из Челябинска (+05:00) такой в 12:00 создал запись и видит 12:00, о, думает всё нормально. А теперь в эту же запись (в это время или же назаватра) смотрит юзер из Москвы (+03:00) и какое время он видит то? 12:00 что ли? Если 12:00, то это жесть полная. Если 10:00 то как раз в этом вопрос — непонятно как это сделано, если, блин, вы не знаете что такое 12:00 на самом деле и в какой таймзоне («локальное время пользователя»).
Ну а с законодательным изменением часовых поясов еще не сталкивались, разработка началась после последнего изменения.
Вы бы описали подробнее свое приложение, а то выглядит как будто вы сначала создали себе проблему, а потом героически ее решили, притом непонятно с какой целью.
У вас не бывает случая, когда несколько пользователей работают с одной БД? Почему обязательно нужна конвертация на стороне БД, а не в PHP? И кстати почему вью, а не процедура?
Т.к. все универсально и индивидуально, то каждому пользователю и выделяется своя БД, вернее даже 4 штуки, основная, файловая, для безопасных ссылок и бд для логов. Я некоторые из технических реализаций этих вещей в следующих статьях буду описывать. Еще много всего интересного можно написать, следующая думаю будет звучать «Как вести логи изменений данных пользователями в базе данных, сохраняя их в другой базе данных (чтобы основная база данных не засорялась мусором и не росла)» — интереснейшая вещь была с технической точки зрения.
View — так проще, как в запросе вы процедуру планируете использовать, left join? это неудобно, а тут просто вместо например timestamp пишете d_timestamp и все работает.
>> Благодаря этому, во всех записях в БД всегда будет проставляться время пользователя => а потом примут закон о смещении часовых поясов и корректность прошлых данных накроется медным тазом.
Тут конечно вопрос что вам необходимо, но проработав 10 лет в телекоме я никогда не сталкивался с тем чтобы делать подобные анализы и тем более со 100% точностью. Детализации делали, да, но там юникстайм который был на оборудовании и никто не заморачивался. В случае перехода на зимнелетнее время получалось что траифк писался 2:59, потом 2:00. Грубо говоря час накладывался друг на друга (или был промежуток в другом случае)
Как сделать разный часовой пояс в разных базах данных на одном сервере