Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datetime formatting problem with Russian timezones #5128

Closed
RomeroMsk opened this issue Sep 22, 2014 · 12 comments
Closed

Datetime formatting problem with Russian timezones #5128

RomeroMsk opened this issue Sep 22, 2014 · 12 comments
Assignees
Labels
type:docs Documentation
Milestone

Comments

@RomeroMsk
Copy link
Contributor

I've encountered very nasty situation with IntlDateFormatter which is used now inside Formatter component. Just want to warn another developers (and maybe it could be included into docs).
I'm using Russian timezones: Europe/Moscow, for example (GMT +4). And today I've noticed that formatting 01.02.2014 00:00:00 value to php:Y-m-d H:i:s is giving 2014-01-31 23:00:00. After some investigation I've found the root of this problem: an outdated time zone DB inside ICU lib (which is used by Intl extension). ICU is not using system TZ data, but using its own TZ database files :-(
Our server is using ICU 4.2 which contains a 2009j version of timezone database. But there was a timezone change in Russia in 2011. So to override the problem we need to use newer version of ICU (or TZ data inside ICU). Here is the last stable version of ICU: http://site.icu-project.org/download/53, but it uses only 2014b timezone database. ICU 54 (with 2014g) is in RC and not recommended for production now: http://site.icu-project.org/download/54. But on October, 2014 timezones will be changed again in Russia, so all developers must use newest TZ data (2014f or newer) inside ICU (not only in OS) to help their Russian users to not experience such issues.

Can anyone confirm this problem? Check your version of ICU (in Configuration tab of debugger toolbar, for example) and try to format the date before 2014-03-31 with Europe/Moscow timezone like this:

$formatter = new \yii\i18n\Formatter;
$formatter->datetimeFormat = 'php:Y-m-d H:i:s';
$formatter->timeZone = 'Europe/Moscow';
echo $formatter->asDateTime('01.02.2014');

If you see 2014-01-31 23:00:00, you have this issue too.

@cebe cebe self-assigned this Sep 22, 2014
@cebe
Copy link
Member

cebe commented Sep 22, 2014

Will look into this and see if we can provide a configuration setting for the tzdata to use.

@cebe cebe added this to the 2.0 GA milestone Sep 22, 2014
@RomeroMsk
Copy link
Contributor Author

Thanks, @cebe. Also, I think that current implementation is not good for date formatting. Let's see at this example:

$formatter = new \yii\i18n\Formatter;
$formatter->dateFormat = 'php:Y-m-d';
$formatter->timeZone = 'UTC';
echo $formatter->asDate('2014-02-01');

We will get 2014-01-31. It is very unexpectedly, yes? :-)

@cebe
Copy link
Member

cebe commented Sep 22, 2014

Thats a general problem with dates, when I create something on 2014-02-01 somewhere on the world it is not the 2014-02-01 but the 2014-01-31 ;) hard to change that. You need to store complete timestamps and convert them to the correct timezone. When only storing the date it is hard to find a correct solution for that.

@RomeroMsk
Copy link
Contributor Author

What can you suggest to use when I need just change a date format of a string? For example, when user input is 01.02.2014 and I need to convert it to 2104-02-01. I thought that Formatter component is useful for that, but now I see that it's not.

@cebe
Copy link
Member

cebe commented Sep 22, 2014

when you ensure you stay in the same timezone for both input and output it should be fine... needs to make some tests to make sure there is not a bug.

@cebe cebe modified the milestones: 2.0 RC, 2.0 GA Sep 22, 2014
@TerraSkye
Copy link
Contributor

When u are developing a website/application that has to do with timezones u need to save it as utc date and present it to the frontend with the right timezone. An usefull tool for this is to use the datetime object u can change the timezone of it to get the right representation for every timezone.

@RomeroMsk
Copy link
Contributor Author

Yes, I understand, that in multi-timezone applications I need to store datetime values in one general timezone. But my problem described in first message is not related to multi-timezone application: I just converted a date (changed format without changing the TZ) and got very strange results (because of ICU outdated TZ data). The second message was just an opinion about Formatter implementation.

@qiangxue qiangxue modified the milestones: 2.0 GA, 2.0 RC Sep 27, 2014
cebe added a commit that referenced this issue Sep 30, 2014
@cebe
Copy link
Member

cebe commented Sep 30, 2014

Multi-timezone support was not working correctly before. This is fixed by 6267b9e

@RomeroMsk can you test again with the latest code? Regarding the outdated timezone db, can you check whether installing the pecl timezonedb as described in http://php.net/manual/en/timezones.php fixes your problem?

@RomeroMsk
Copy link
Contributor Author

@cebe, I can't test it now, because we've upgraded ICU TZ data to the newest one.
Also I know that ICU doesn't use PECL timezonedb (you can read about it here: http://userguide.icu-project.org/datetime/timezone). When I've found this problem, we had actual system and PECL timezone DBs, so installing new PECL timezonedb won't fix this problem.

@cebe cebe closed this as completed in 01487aa Oct 6, 2014
@cebe
Copy link
Member

cebe commented Oct 6, 2014

Thanks, added the information to the guide.

@Yiivgeny
Copy link

At first, method formatDateTimeValue is dirty, because use two timezonedb for one operation. Time-to-object (with php tzdb), then object-to-string (with icu tzdb)

$DT = new \DateTime;
var_dump($DT->format('c')); //2015-12-17T17:05:02+03:00
var_dump(\Yii::$app->getFormatter()->asDatetime($DT)); //17 дек. 2015 г., 18:05:02

Assume, it's server software problem, but input value already contain TZ info, why not use it for cleanly behavior?

At second, updating timezonedb so hard on some systems, e.g. CentOS 6.x (with all updates and enabled popular update repos) now contain old libicu (Version: 50.1.2 Release Date: 2012-12-17). Updating (http://habrahabr.ru/post/241447/) is not trivial and stable.

I suggest, pass tz-argument for instantiate IntlDateFormatter as offset string (getted from \DateTime object). Result:

  1. Narrow updates to only php-related tzdata (more friendly framework installing)
  2. For not-updated environments behavior more cleanly (same result for internal and intl conversions)
  3. Full BC, in my oppinion.

I can create PR for it.

@cebe
Copy link
Member

cebe commented Dec 18, 2015

@Yiivgeny please open a new issue, this one is really old.

@yiisoft yiisoft locked and limited conversation to collaborators Dec 18, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type:docs Documentation
Projects
None yet
Development

No branches or pull requests

6 participants