doctrine-extensions icon indicating copy to clipboard operation
doctrine-extensions copied to clipboard

Fix convert_tz function in Postgresql

Open mesolaries opened this issue 2 years ago • 6 comments

$toTz parameter was passed before $fromTz. It causes convert_tz function to work not as expected. This pr fixes this bug.

mesolaries avatar Apr 05 '22 13:04 mesolaries

@x86demon please review

mesolaries avatar Apr 06 '22 13:04 mesolaries

@x86demon This issue tripped me up for quite a while as well.

paulferrett avatar Oct 13 '22 00:10 paulferrett

@mesolaries thank you for your PR and fix. Please update tests to show the bug and correctness of the fix.

Sorry for delay in the answer.

x86demon avatar Oct 13 '22 10:10 x86demon

I've checked CONVERT_TZ and it works as expected. As a source of this implementation MySQL CONVERT_TZ was taken. https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_convert-tz DQL function should return same results for both supported platforms (MySQL and PostgreSQL) I've used next example MySQL

mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','UTC','Europe/Kiev');
+-------------------------------------------------------+
| CONVERT_TZ('2004-01-01 12:00:00','UTC','Europe/Kiev') |
+-------------------------------------------------------+
| 2004-01-01 14:00:00                                   |
+-------------------------------------------------------+

Current implementation for PostgreSQL

postgres=# SELECT "timestamp"('2004-01-01 12:00:00' AT TIME ZONE 'Europe/Kiev' AT TIME ZONE 'UTC');
      timestamp      
---------------------
 2004-01-01 14:00:00

I'm closing the PR

@mesolaries, @paulferrett thank you for paying attention.

x86demon avatar Oct 18 '22 10:10 x86demon

@x86demon Your example is not the same as current PostgreSQL implementation. Parenthesis are in wrong place. Your example: SELECT "timestamp"('2004-01-01 12:00:00' AT TIME ZONE 'Europe/Kiev' AT TIME ZONE 'UTC'); Actual implementation: SELECT "timestamp"('2004-01-01 12:00:00') AT TIME ZONE 'Europe/Kiev' AT TIME ZONE 'UTC';

https://github.com/oroinc/doctrine-extensions/blob/67eda39d5e94fa25d105c759673bc45a5256798f/src/Oro/ORM/Query/AST/Platform/Functions/Postgresql/ConvertTz.php#L22-L24

So, let's assume I want to convert datetime from UTC timezone to Europe/Kiev timezone. I will take current implementation as example. Expected output: 2004-01-01T14:00:00.000Z

postgres=# SELECT "timestamp"('2004-01-01 12:00:00') AT TIME ZONE 'Europe/Kiev' AT TIME ZONE 'UTC';
      timestamp      
---------------------
2004-01-01T10:00:00.000Z

As you can see the output is wrong. This is because $fromTz parameter is passed after $toTz as I mentioned before.

mesolaries avatar Oct 18 '22 12:10 mesolaries

@mesolaries you are right, I've missed parentheses position. Please update test so I'll be able to merge the PR

x86demon avatar Oct 18 '22 12:10 x86demon