Fix parsing of time string followed by yesterday/today/tomorrow.
authorRobert Haas <rhaas@postgresql.org>
Tue, 30 Aug 2011 15:34:29 +0000 (11:34 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 30 Aug 2011 15:38:42 +0000 (11:38 -0400)
Previously, 'yesterday 04:00:00'::timestamp didn't do the same thing as
'04:00:00 yesterday'::timestamp, and the return value from the latter
was midnight rather than the specified time.

Dean Rasheed, with some stylistic changes

src/backend/utils/adt/datetime.c
src/test/regress/expected/horology.out
src/test/regress/sql/horology.sql

index 3d320ccdd58ee3784a5c2eef59163136ea0c8c5a..dad41fc20e5b19c7dd521d2277250a47189196bd 100644 (file)
@@ -799,6 +799,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
    bool        is2digits = FALSE;
    bool        bc = FALSE;
    pg_tz      *namedTz = NULL;
+   struct pg_tm cur_tm;
 
    /*
     * We'll insist on at least all of the date fields, but initialize the
@@ -1197,32 +1198,26 @@ DecodeDateTime(char **field, int *ftype, int nf,
                            case DTK_YESTERDAY:
                                tmask = DTK_DATE_M;
                                *dtype = DTK_DATE;
-                               GetCurrentDateTime(tm);
-                               j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1,
+                               GetCurrentDateTime(&cur_tm);
+                               j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) - 1,
                                    &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-                               tm->tm_hour = 0;
-                               tm->tm_min = 0;
-                               tm->tm_sec = 0;
                                break;
 
                            case DTK_TODAY:
                                tmask = DTK_DATE_M;
                                *dtype = DTK_DATE;
-                               GetCurrentDateTime(tm);
-                               tm->tm_hour = 0;
-                               tm->tm_min = 0;
-                               tm->tm_sec = 0;
+                               GetCurrentDateTime(&cur_tm);
+                               tm->tm_year = cur_tm.tm_year;
+                               tm->tm_mon = cur_tm.tm_mon;
+                               tm->tm_mday = cur_tm.tm_mday;
                                break;
 
                            case DTK_TOMORROW:
                                tmask = DTK_DATE_M;
                                *dtype = DTK_DATE;
-                               GetCurrentDateTime(tm);
-                               j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1,
+                               GetCurrentDateTime(&cur_tm);
+                               j2date(date2j(cur_tm.tm_year, cur_tm.tm_mon, cur_tm.tm_mday) + 1,
                                    &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
-                               tm->tm_hour = 0;
-                               tm->tm_min = 0;
-                               tm->tm_sec = 0;
                                break;
 
                            case DTK_ZULU:
index b13f7d7c5b531b41aaab96439748265b1e0a3609..8526765967c65c361710e68d2a8fa24e9de0da3f 100644 (file)
@@ -388,12 +388,48 @@ SELECT (timestamp without time zone 'today' = (timestamp without time zone 'tomo
  t
 (1 row)
 
+SELECT (timestamp without time zone 'today 10:30' = (timestamp without time zone 'yesterday' + interval '1 day 10 hr 30 min')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp without time zone '10:30 today' = (timestamp without time zone 'yesterday' + interval '1 day 10 hr 30 min')) as "True";
+ True 
+------
+ t
+(1 row)
+
 SELECT (timestamp without time zone 'tomorrow' = (timestamp without time zone 'yesterday' + interval '2 days')) as "True";
  True 
 ------
  t
 (1 row)
 
+SELECT (timestamp without time zone 'tomorrow 16:00:00' = (timestamp without time zone 'today' + interval '1 day 16 hours')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp without time zone '16:00:00 tomorrow' = (timestamp without time zone 'today' + interval '1 day 16 hours')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp without time zone 'yesterday 12:34:56' = (timestamp without time zone 'tomorrow' - interval '2 days - 12:34:56')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp without time zone '12:34:56 yesterday' = (timestamp without time zone 'tomorrow' - interval '2 days - 12:34:56')) as "True";
+ True 
+------
+ t
+(1 row)
+
 SELECT (timestamp without time zone 'tomorrow' > 'now') as "True";
  True 
 ------
@@ -603,12 +639,54 @@ SELECT (timestamp with time zone 'today' = (timestamp with time zone 'tomorrow'
  t
 (1 row)
 
+SELECT (timestamp with time zone 'today 10:30+05' = timestamptz(date 'today', time with time zone '10:30 +05')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp with time zone '10:30+05 today' = timestamptz(date 'today', time with time zone '10:30 +05')) as "True";
+ True 
+------
+ t
+(1 row)
+
 SELECT (timestamp with time zone 'tomorrow' = (timestamp with time zone 'yesterday' + interval '2 days')) as "True";
  True 
 ------
  t
 (1 row)
 
+SELECT (timestamp with time zone 'tomorrow 10:30+05' = (timestamp with time zone 'today 10:30+05' + interval '1 day')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp with time zone '10:30+05 tomorrow' = (timestamp with time zone 'today 10:30+05' + interval '1 day')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp with time zone 'yesterday 12:34:56-7' = timestamptz(date 'yesterday', time with time zone '12:34:56-7')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp with time zone '12:34:56 yesterday -7' = timestamptz(date 'yesterday', time with time zone '12:34:56-7')) as "True";
+ True 
+------
+ t
+(1 row)
+
+SELECT (timestamp with time zone '12:34:56-7 yesterday' = timestamptz(date 'yesterday', time with time zone '12:34:56-7')) as "True";
+ True 
+------
+ t
+(1 row)
+
 SELECT (timestamp with time zone 'tomorrow' > 'now') as "True";
  True 
 ------
index 97ff9f20c798f421df911c44144557de5bb79c08..e9981e586a52fa777cbcb9e67e1c7e1b4e811945 100644 (file)
@@ -91,7 +91,13 @@ SELECT timestamp without time zone '12/31/294276' - timestamp without time zone
 -- So, just try to test parser and hope for the best - thomas 97/04/26
 SELECT (timestamp without time zone 'today' = (timestamp without time zone 'yesterday' + interval '1 day')) as "True";
 SELECT (timestamp without time zone 'today' = (timestamp without time zone 'tomorrow' - interval '1 day')) as "True";
+SELECT (timestamp without time zone 'today 10:30' = (timestamp without time zone 'yesterday' + interval '1 day 10 hr 30 min')) as "True";
+SELECT (timestamp without time zone '10:30 today' = (timestamp without time zone 'yesterday' + interval '1 day 10 hr 30 min')) as "True";
 SELECT (timestamp without time zone 'tomorrow' = (timestamp without time zone 'yesterday' + interval '2 days')) as "True";
+SELECT (timestamp without time zone 'tomorrow 16:00:00' = (timestamp without time zone 'today' + interval '1 day 16 hours')) as "True";
+SELECT (timestamp without time zone '16:00:00 tomorrow' = (timestamp without time zone 'today' + interval '1 day 16 hours')) as "True";
+SELECT (timestamp without time zone 'yesterday 12:34:56' = (timestamp without time zone 'tomorrow' - interval '2 days - 12:34:56')) as "True";
+SELECT (timestamp without time zone '12:34:56 yesterday' = (timestamp without time zone 'tomorrow' - interval '2 days - 12:34:56')) as "True";
 SELECT (timestamp without time zone 'tomorrow' > 'now') as "True";
 
 -- Convert from date and time to timestamp
@@ -112,7 +118,14 @@ SELECT timestamp with time zone '1999-12-01' + interval '1 month - 1 second' AS
 
 SELECT (timestamp with time zone 'today' = (timestamp with time zone 'yesterday' + interval '1 day')) as "True";
 SELECT (timestamp with time zone 'today' = (timestamp with time zone 'tomorrow' - interval '1 day')) as "True";
+SELECT (timestamp with time zone 'today 10:30+05' = timestamptz(date 'today', time with time zone '10:30 +05')) as "True";
+SELECT (timestamp with time zone '10:30+05 today' = timestamptz(date 'today', time with time zone '10:30 +05')) as "True";
 SELECT (timestamp with time zone 'tomorrow' = (timestamp with time zone 'yesterday' + interval '2 days')) as "True";
+SELECT (timestamp with time zone 'tomorrow 10:30+05' = (timestamp with time zone 'today 10:30+05' + interval '1 day')) as "True";
+SELECT (timestamp with time zone '10:30+05 tomorrow' = (timestamp with time zone 'today 10:30+05' + interval '1 day')) as "True";
+SELECT (timestamp with time zone 'yesterday 12:34:56-7' = timestamptz(date 'yesterday', time with time zone '12:34:56-7')) as "True";
+SELECT (timestamp with time zone '12:34:56 yesterday -7' = timestamptz(date 'yesterday', time with time zone '12:34:56-7')) as "True";
+SELECT (timestamp with time zone '12:34:56-7 yesterday' = timestamptz(date 'yesterday', time with time zone '12:34:56-7')) as "True";
 SELECT (timestamp with time zone 'tomorrow' > 'now') as "True";
 
 -- timestamp with time zone, interval arithmetic around DST change