pgsql named time zone detection is incorrect

beginner - July 6, 2008 - 10:36
Project:Date
Version:6.x-2.x-dev
Component:Code
Category:bug report
Priority:normal
Assigned:Unassigned
Status:closed
Description

While browsing the files trying to understand what does what, I came across an obvious error in date_sql_handler::db_tz_support() :

<?php
       
case 'mysqli':
         
$test = db_result(db_query("SELECT CONVERT_TZ('2008-02-15 12:00:00', 'UTC', 'US/Central')"));
          if (
$test == '2008-02-15 06:00:00') {
           
$has_support = TRUE;
          }
          break;
        case
'pgsql':
         
$test = "TIMESTAMP WITH TIME ZONE '2008-02-15 12:00:00' AT TIME ZONE 'US/Central'";
          if (
$test == '2008-02-15 06:00:00') {
           
$has_support = TRUE;
          }
?>

db_result(db_query()) is missing in case 'pgsql'.

#1

heyrocker - July 7, 2008 - 19:57
Title:pgsql error» pgsql named time zone detection is incorrect

The actual query is incorrect too. I'm attempting to come up with a proper SQL query to do what is needed. Postgres seems to always want to convert everything to its current timezone, so converting between two random timezones in one SQL query is problematic, unless I'm totally missing the boat which is quite possible.

#2

jmpoure - July 7, 2008 - 21:51

The correct SQL for PostgreSQL is:

SELECT '2008-02-15 12:00:00 UTC' AT TIME ZONE 'US/Central';

You can also use PostgreSQL built-in funtion:
SELECT timezone('US/Central', '2008-02-15 12:00:00 UTC')

Both queries return:
2008-02-15 06:00:00

Patch:

Index: date_api_sql.inc
===================================================================
--- date_api_sql.inc (révision 89)
+++ date_api_sql.inc (copie de travail)
@@ -76,7 +76,7 @@
           }
           break;
         case 'pgsql':
-          $test = "TIMESTAMP WITH TIME ZONE '2008-02-15 12:00:00' AT TIME ZONE 'US/Central'";
+          $test = db_result(db_query("SELECT timezone('US/Central', '2008-02-15 12:00:00 UTC')"));
           if ($test == '2008-02-15 06:00:00') {
             $has_support = TRUE;
           }
@@ -240,9 +240,7 @@
         case 'mysqli':
           return "CONVERT_TZ($field, $db_zone, $localzone)";
         case 'pgsql':
-          // WITH TIME ZONE assumes the date is using the system
-          // timezone, which should have been set to UTC.
-          return "TIMESTAMP WITH TIME ZONE $field AT TIME ZONE $localzone";
+          return "timezone('$localzone', '$field $db_zone')";
       }
     }
   }
@@ -730,4 +728,4 @@
       return array($min_date, $max_date);
     }
   }
-}
\ No newline at end of file
+}

I tested only the SQL.

Hope this helps.
JMP

#3

jmpoure - July 7, 2008 - 21:49
Status:active» patch (code needs review)

Status: patch needs review.

#4

heyrocker - July 8, 2008 - 01:05

Thanks for that SQL, it is exactly what was needed.

I found a potential problem involving embedded quotes in your change to sql_tz(), but in the interests of tackling one thing per issue I think we should just address the problem in db_tz_support() right now. Patch attached, with a very minor formatting tweak. I'll open another issue for the sql_tz() problem.

Edit: and I decided not to pending a little more research.

AttachmentSize
279501.patch491 bytes

#5

KarenS - July 8, 2008 - 02:18

I committed the first part, the db_tz_support(). I'm unclear about the status of the second fix. Also, if it's correct, is it OK to capitalize TIMEZONE for consistency in the code?

#6

heyrocker - July 8, 2008 - 23:00

jmpoure, can you elaborate on the change to timezone? It seems to me like the original should be fine but my experience with Postgres is not terribly extensive.

#7

KarenS - July 24, 2008 - 21:08
Status:patch (code needs review)» fixed

No response on this. If the remaining issue is just another valid way to structure the postgres code, there's no reason to change anything.

#8

Anonymous (not verified) - August 7, 2008 - 21:14
Status:fixed» closed

Automatically closed -- issue fixed for two weeks with no activity.

 
 

Drupal is a registered trademark of Dries Buytaert.