Skip to content

DateTimeToLocalizedStringTransformer ignoring time during reverse transform between timezones #20806

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

Closed
rcwsr opened this issue Dec 7, 2016 · 7 comments

Comments

@rcwsr
Copy link

rcwsr commented Dec 7, 2016

Updating from symfony v2.8.9 to v.2.8.10 one of my project's tests has started to fail, it looks like it was introduced here c951bb6

I'm not entirely sure if it's a bug with symfony or my project, as it looks like that commit purposely ignores datetime strings without a time.

I have reproduced my project's failing test in DateTimeToLocalizedStringTransformerTest: rcwsr@f605b85

1) Symfony\Component\Form\Tests\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformerTest::testReverseTransformDateWithoutTime
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'1420088400'
+'1420070400'
@Jean85
Copy link
Contributor

Jean85 commented Dec 14, 2016

The reverse transformation ignores text without time because time zones influences just time. If you are inputting a date, you wouldn't like that to be changed because the system is implying 00:00:00 and that means the previous day in a latter timezone.

Maybe the behavior is not perfect, but that stems from the fact that PHP doesn't have a \Date type, so we are forced to set a time somewhere; but if we changed it, it would fail otherwise with this example:

    public function testReverseTransformDateWithoutTime()
    {
        $transformer = new DateTimeToLocalizedStringTransformer(
            'UTC',
            'America/Louisville',
            \IntlDateFormatter::FULL,
            \IntlDateFormatter::FULL,
            \IntlDateFormatter::GREGORIAN,
            'yyyy-MM-dd'
        );

        $date = new \DateTime('2015-01-01T05:00:00+00:00');
        $this->assertEquals(
            $date->format('Y-m-d'),
            $transformer->reverseTransform('2015-01-01')->format('Y-m-d')
        );
    }

..which is the "normal" behavior of a programmer: using implied timezone (which probably isn't UTC).

@issei-m
Copy link
Contributor

issei-m commented Jan 25, 2017

This problem seems to be caused by IntlDateFormatter stubs.
In my env, a generated timestamp completely differs between stubs and native. A former one seems to not deal with the timezone something properly.

/cc @webmozart @HeahDude

@HeahDude
Copy link
Contributor

HeahDude commented Jan 25, 2017

@issei-m this issue should have been fixed in #21218 as of 2.7.23, 2.8.16, 3.1.9, 3.2.2, could you please confirm?

@Jean85
Copy link
Contributor

Jean85 commented Jan 25, 2017

Damn, this reverses a previous PR where I was involved. I understand why is that like that, but now I'm just desiring so bad a \Date object in PHP...

@issei-m
Copy link
Contributor

issei-m commented Jan 26, 2017

@HeahDude I don't think so. As before I said, this problem doesn't seem to be DateTimeToLocalizedStringTransformer's matter. This problem is caused by \Symfony\Component\Intl\DateFormatter\IntlDateFormatter in Intl component. (So you wouldn't encounter if you're using a native one)

See following snippet - the POC for my opinion on my env (PHP 7.0):

date_default_timezone_set('Asia/Tokyo'); // My timezone.

$pattern = 'yyyy-MM-dd';

$nativeIntlDf = new \IntlDateFormatter('en', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, 'UTC', \IntlDateFormatter::GREGORIAN, $pattern);
$polyfillIntlDf = new \Symfony\Component\Intl\DateFormatter\IntlDateFormatter('en', \IntlDateFormatter::FULL, \IntlDateFormatter::FULL, 'UTC', \IntlDateFormatter::GREGORIAN, $pattern);

var_dump(
    $nativeIntlDf->parse('2017-01-01'),  // 1483228800
    $polyfillIntlDf->parse('2017-01-01') // 1483196400
);
  • A former one (1483228800) is care about a timezone well - it's 2017/01/01 00:00:00 in UTC
  • But a latter one (1483196400) doesn't - it's 2016-12-31 15:00:00 in UTC (In other words, it's influenced by the current timezone)

This timestamp is passed to gmdate('Y-m-d') at here, eventually the result of a latter one is DateTime('2016-12-31 00:00:00', 'UTC').
As you can see, although this datetime object is set specific TZ after this, the final date would end up with wrong.

So we have to fix \Symfony\Component\Intl\DateFormatter\IntlDateFormatter, at least as well as native works IMHO.

Regards.

@issei-m
Copy link
Contributor

issei-m commented Jan 27, 2017

I've just opened a new issue about this problem.

@HeahDude
Copy link
Contributor

Ok, thanks! Let's close here then as the original issue is about the transformer and has been fixed by #21218.

@xabbuh xabbuh closed this as completed Jan 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants