timezone у пользователя

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Аватара пользователя
maleks
Сообщения: 1769
Зарегистрирован: 2012.12.26, 12:56

timezone у пользователя

Сообщение maleks » 2015.10.06, 16:34

Привет.
Вроде ясно, но уточнить все ли верно делаю.
Для зареганых пользователей хочу в ихнем профиле сделать поле "Ваш часовой пояс", в нем пользователь выберет из списка зону, например 'Europe/Helsinki' и я ее сохраню в таблицу users.
И теперь при каждом запросе при инициализации объекта идентификации через Yii::$app-> timezone = $user->timezone буду выставлять текущую зону пользователя.
Вывод дат-времени через форматтер ну или date()
Храню в самом движке цмс даты-время как unixtimestamp и этими числами и оперирую.
Этого будет достаточно для корректной работы?

Аватара пользователя
vitalik1183
Сообщения: 1673
Зарегистрирован: 2014.07.01, 08:42

Re: timezone у пользователя

Сообщение vitalik1183 » 2015.10.06, 16:36

вопщем то да. только зачем хранить в юникстайме?
Yii2!

Аватара пользователя
maleks
Сообщения: 1769
Зарегистрирован: 2012.12.26, 12:56

Re: timezone у пользователя

Сообщение maleks » 2015.10.07, 07:15

то сейчас делаю ядро движка, чтобы было одинаково для разных баз. Число оно везде число, а специфичные типы полей разнятся. Да и в друпале так делается, значит неспроста.

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: timezone у пользователя

Сообщение zelenin » 2015.10.07, 10:24

maleks писал(а):то сейчас делаю ядро движка, чтобы было одинаково для разных баз
все базы поддерживают формат iso8601
maleks писал(а):Число оно везде число, а специфичные типы полей разнятся.
см. выше
maleks писал(а):Да и в друпале так делается, значит неспроста.
а в базах неспроста делают типы полей дат

Аватара пользователя
S c
Сообщения: 875
Зарегистрирован: 2012.04.11, 14:46

Re: timezone у пользователя

Сообщение S c » 2015.10.07, 10:41

А чем плохо хранить в unixtime? Геморой при выборке периода?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: timezone у пользователя

Сообщение zelenin » 2015.10.07, 10:48

S c писал(а):А чем плохо хранить в unixtime? Геморой при выборке периода?
ну для начала unixtime - это не дата, а число.

Аватара пользователя
vitalik1183
Сообщения: 1673
Зарегистрирован: 2014.07.01, 08:42

Re: timezone у пользователя

Сообщение vitalik1183 » 2015.10.07, 10:49

ой это извечная дискуссия как лучше хранить. Все зависит от задачи. Мне вот DATETIME более нравится, я его юзаю везде и не знаю проблем ни с часовыми поясами ни с выборками.
Yii2!

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: timezone у пользователя

Сообщение zelenin » 2015.10.07, 10:51

vitalik1183 писал(а):ой это извечная дискуссия как лучше хранить. Все зависит от задачи. Мне вот DATETIME более нравится, я его юзаю везде и не знаю проблем ни с часовыми поясами ни с выборками.
+1

Аватара пользователя
S c
Сообщения: 875
Зарегистрирован: 2012.04.11, 14:46

Re: timezone у пользователя

Сообщение S c » 2015.10.07, 11:38

vitalik1183 писал(а):ой это извечная дискуссия как лучше хранить. Все зависит от задачи. Мне вот DATETIME более нравится, я его юзаю везде и не знаю проблем ни с часовыми поясами ни с выборками.
так это уже совсем другой разговор :)

Аватара пользователя
maleks
Сообщения: 1769
Зарегистрирован: 2012.12.26, 12:56

Re: timezone у пользователя

Сообщение maleks » 2015.10.07, 13:38

vitalik1183 писал(а):ой это извечная дискуссия как лучше хранить. Все зависит от задачи. Мне вот DATETIME более нравится, я его юзаю везде и не знаю проблем ни с часовыми поясами ни с выборками.
для него надо на уровне mysql устанавливать зону, так - SET time_zone='+03:00' ? (отсюда)

Аватара пользователя
S c
Сообщения: 875
Зарегистрирован: 2012.04.11, 14:46

Re: timezone у пользователя

Сообщение S c » 2015.10.07, 14:10

maleks писал(а):
vitalik1183 писал(а):ой это извечная дискуссия как лучше хранить. Все зависит от задачи. Мне вот DATETIME более нравится, я его юзаю везде и не знаю проблем ни с часовыми поясами ни с выборками.
для него надо на уровне mysql устанавливать зону, так - SET time_zone='+03:00' ? (отсюда)
такой подход не учитывает летнее зимнее время, могу ошибаться. Лучше "America/Toronto"
+ DATETIME Хранит время не зависимо от часового пояса

Аватара пользователя
S c
Сообщения: 875
Зарегистрирован: 2012.04.11, 14:46

Re: timezone у пользователя

Сообщение S c » 2015.10.07, 14:21

Код: Выделить всё

<?php
$date = new DateTime('2000-01-01', new DateTimeZone('Pacific/Nauru'));
echo $date->format('Y-m-d H:i:sP') . "\n";

$date->setTimezone(new DateTimeZone('Pacific/Chatham'));
echo $date->format('Y-m-d H:i:sP') . "\n";
?>
//2000-01-01 00:00:00+12:00
//2000-01-01 01:45:00+13:45
Просто вывод это одно, а как быть с выборкой? Верно я понимаю?
1) Храним все даты в любом случае в UTC
2) Выбрал пользователь на фильтре 2 даты (с временем)
3) Корректируем эти значения с учетом часового пояса пользователя (переводим в UTC)
4) И уже делаем выборку стандартными sql datetime функциями

Или есть иной подход? Я просто привык с timestamp-ом работать

Аватара пользователя
vitalik1183
Сообщения: 1673
Зарегистрирован: 2014.07.01, 08:42

Re: timezone у пользователя

Сообщение vitalik1183 » 2015.10.07, 14:43

Вопщем то да, но у меня 99% выборок сводится только к дате, я со временем редко сталкиваюсь. Минуты и секунды нужны для вывода, а фильтры у меня по датам. Но я раньше тоже был ярым приверженцем хранить дату в виде числа, потом как то перешел на DATETIME изза встроенных в mysql функций сравнения и манипуляции с датой. Честно говоря и с часовыми поясами что то никогда не было проблем.
Yii2!

Аватара пользователя
S c
Сообщения: 875
Зарегистрирован: 2012.04.11, 14:46

Re: timezone у пользователя

Сообщение S c » 2015.10.07, 15:14

vitalik1183 писал(а):Вопщем то да, но у меня 99% выборок сводится только к дате, я со временем редко сталкиваюсь. Минуты и секунды нужны для вывода, а фильтры у меня по датам. Но я раньше тоже был ярым приверженцем хранить дату в виде числа, потом как то перешел на DATETIME изза встроенных в mysql функций сравнения и манипуляции с датой. Честно говоря и с часовыми поясами что то никогда не было проблем.
даже если чисто с датами - в одном часовом поясе сегодня 21 число, в другом 22. В любом случае преобразования нужно будет делать.

Аватара пользователя
maleks
Сообщения: 1769
Зарегистрирован: 2012.12.26, 12:56

Re: timezone у пользователя

Сообщение maleks » 2015.10.08, 08:21

zelenin писал(а):
maleks писал(а):то сейчас делаю ядро движка, чтобы было одинаково для разных баз
все базы поддерживают формат iso8601
Ну а профит, если манипуляции в базах разнятся, например для mysql я выполняю запрос
select NOW(), NOW() + interval 1 DAY
а для postgre нужно задавать в формате с кавычками: interval '1 hour'
, в mysql если с кавычками указать то ошибка запроса.

Аватара пользователя
maleks
Сообщения: 1769
Зарегистрирован: 2012.12.26, 12:56

Re: timezone у пользователя

Сообщение maleks » 2015.10.08, 10:48

подзабыл workflow с идентификацией пользователя.
Где мне надо выставить эту его временную зону? Думал сначала в findIdentity объекта идентификации, но смотрю что это же затребуется по требованию идентификации и может быть позже необходимого.
На Application::EVENT_BEFORE_REQUEST повесить проверку что не гость и есть временная зона то установить или как то покрасивей?

zelenin
Сообщения: 10596
Зарегистрирован: 2013.04.20, 11:30

Re: timezone у пользователя

Сообщение zelenin » 2015.10.08, 11:43

maleks писал(а):
zelenin писал(а):
maleks писал(а):то сейчас делаю ядро движка, чтобы было одинаково для разных баз
все базы поддерживают формат iso8601
Ну а профит, если манипуляции в базах разнятся, например для mysql я выполняю запрос
select NOW(), NOW() + interval 1 DAY
а для postgre нужно задавать в формате с кавычками: interval '1 hour'
, в mysql если с кавычками указать то ошибка запроса.
а в mysql нет таких замечательных ранжирующих методов как row_number(), rank(), dense_rank(), нет встроенной поддержки matherialized path, поддержки json и массивов и прочее. Чуть бОльшее приложение чем "ничто", и ты уже не в состоянии построить портабельное приложение, независящее от субд, т.к. встроенный query builder покрывает только базис языка (sql).

Аватара пользователя
maleks
Сообщения: 1769
Зарегистрирован: 2012.12.26, 12:56

Re: timezone у пользователя

Сообщение maleks » 2015.10.09, 09:38

Оставлю ссылку на хороший код формирования списка зон для вывода:
http://pastebin.com/iqVjyFjE

Аватара пользователя
maleks
Сообщения: 1769
Зарегистрирован: 2012.12.26, 12:56

Re: timezone у пользователя

Сообщение maleks » 2015.10.09, 10:23

Интересно почему для вот этих строк с intl значениями игнорируется текущая зона?

Код: Выделить всё

echo "PHP: " . PHP_VERSION . "\n";
echo "ICU: " . INTL_ICU_VERSION . "\n";
PHP: 5.4.21 ICU: 49.1.2
PHP: 5.4.21 ICU: 49.1.2
Например есть для app перевод

Код: Выделить всё

'It is {0, time}' => 'Сейчас {0, time}',
Теперь в контроллере:

Код: Выделить всё

        var_dump(Yii::$app->timeZone);
        var_dump(Yii::$app->formatter->timeZone);
        var_dump(Yii::t('app', 'It is {0, time}', time())); // <<==== !!!!!!!!
        var_dump(Yii::$app->formatter->asTime(time()));        
        var_dump(getdate());
Выдаст:

Код: Выделить всё

string 'Atlantic/St_Helena' (length=18)
string 'Atlantic/St_Helena' (length=18)
string 'Сейчас 10:20:47' (length=21)             <<==== !!!!!!!!
string '7:20:47' (length=7)
array (size=11)
  'seconds' => int 47
  'minutes' => int 20
  'hours' => int 7
  'mday' => int 9
  'wday' => int 5
  'mon' => int 10
  'year' => int 2015
  'yday' => int 281
  'weekday' => string 'Friday' (length=6)
  'month' => string 'October' (length=7)
  0 => int 1444375247
Вот там где через intl вот там не учитывает текущую временную зону, т.к. должно быть 7 часов для этой зоны а не 10

Аватара пользователя
S c
Сообщения: 875
Зарегистрирован: 2012.04.11, 14:46

Re: timezone у пользователя

Сообщение S c » 2015.10.09, 11:45

у меня вообще только getdate() корректное время выдает.

Код: Выделить всё

echo "PHP: " . PHP_VERSION . "\n";
echo "ICU: " . INTL_ICU_VERSION . "\n";
$time = time();
var_dump(Yii::$app->timeZone);
var_dump(Yii::$app->formatter->timeZone);
var_dump(date_default_timezone_get());
var_dump(Yii::t('app', 'It is {0, time}', $time));
var_dump(Yii::$app->formatter->asTime($time, 'medium'));
var_dump(getdate());
 

Код: Выделить всё

PHP: 5.5.9-1ubuntu4.13
ICU: 52.1
string(13) "Europe/Moscow"
string(13) "Europe/Moscow"
string(13) "Europe/Moscow"
string(17) "It is 12:42:06 PM"
string(8) "12:42:06"
array(11) {
  ["seconds"]=>
  int(6)
  ["minutes"]=>
  int(42)
  ["hours"]=>
  int(11)
  ["mday"]=>
  int(9)
  ["wday"]=>
  int(5)
  ["mon"]=>
  int(10)
  ["year"]=>
  int(2015)
  ["yday"]=>
  int(281)
  ["weekday"]=>
  string(6) "Friday"
  ["month"]=>
  string(7) "October"
  [0]=>
  int(1444380126)
}

Ответить