Skip to content
Snippets Groups Projects
Commit 4d745dad authored by Thomas G. Lockhart's avatar Thomas G. Lockhart
Browse files

Modify date->timestamp conversion to use mktime().

 This should do better than before around Daylight Savings Time
 transitions.
parent 3bb28381
No related branches found
No related tags found
No related merge requests found
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.49 2000/07/12 22:59:08 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.50 2000/09/12 05:41:37 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -25,10 +25,6 @@ ...@@ -25,10 +25,6 @@
#include "utils/nabstime.h" #include "utils/nabstime.h"
static int date2tm(DateADT dateVal, int *tzp, struct tm * tm,
double *fsec, char **tzn);
/***************************************************************************** /*****************************************************************************
* Date ADT * Date ADT
*****************************************************************************/ *****************************************************************************/
...@@ -230,15 +226,34 @@ date_timestamp(PG_FUNCTION_ARGS) ...@@ -230,15 +226,34 @@ date_timestamp(PG_FUNCTION_ARGS)
Timestamp result; Timestamp result;
struct tm tt, struct tm tt,
*tm = &tt; *tm = &tt;
int tz; time_t utime;
double fsec = 0;
char *tzn;
if (date2tm(dateVal, &tz, tm, &fsec, &tzn) != 0) j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
elog(ERROR, "Unable to convert date to timestamp");
if (tm2timestamp(tm, fsec, &tz, &result) != 0) if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
elog(ERROR, "Timestamp out of range"); {
#ifdef USE_POSIX_TIME
tm->tm_hour = 0;
tm->tm_min = 0;
tm->tm_sec = 0;
tm->tm_isdst = -1;
tm->tm_year -= 1900;
tm->tm_mon -= 1;
utime = mktime(tm);
if (utime == -1)
elog(ERROR, "Unable to convert date to tm");
result = utime + ((date2j(1970,1,1)-date2j(2000,1,1))*86400.0);
#else /* !USE_POSIX_TIME */
result = dateVal*86400.0+CTimeZone;
#endif
}
else
{
/* Outside of range for timezone support, so assume UTC */
result = dateVal*86400.0;
}
PG_RETURN_TIMESTAMP(result); PG_RETURN_TIMESTAMP(result);
} }
...@@ -324,81 +339,6 @@ abstime_date(PG_FUNCTION_ARGS) ...@@ -324,81 +339,6 @@ abstime_date(PG_FUNCTION_ARGS)
} }
/* date2tm()
* Convert date to time structure.
* Note that date is an implicit local time, but the system calls assume
* that everything is GMT. So, convert to GMT, rotate to local time,
* and then convert again to try to get the time zones correct.
*/
static int
date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn)
{
struct tm *tx;
time_t utime;
*fsec = 0;
j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday));
tm->tm_hour = 0;
tm->tm_min = 0;
tm->tm_sec = 0;
tm->tm_isdst = -1;
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
{
/* convert to system time */
utime = ((dateVal + (date2j(2000, 1, 1) - date2j(1970, 1, 1))) * 86400);
/* rotate to noon to get the right day in time zone */
utime += (12 * 60 * 60);
#ifdef USE_POSIX_TIME
tx = localtime(&utime);
tm->tm_year = tx->tm_year + 1900;
tm->tm_mon = tx->tm_mon + 1;
tm->tm_mday = tx->tm_mday;
tm->tm_isdst = tx->tm_isdst;
#if defined(HAVE_TM_ZONE)
tm->tm_gmtoff = tx->tm_gmtoff;
tm->tm_zone = tx->tm_zone;
/* tm_gmtoff is Sun/DEC-ism */
*tzp = -(tm->tm_gmtoff);
if (tzn != NULL)
*tzn = (char *) tm->tm_zone;
#elif defined(HAVE_INT_TIMEZONE)
#ifdef __CYGWIN__
*tzp = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
#else
*tzp = (tm->tm_isdst ? (timezone - 3600) : timezone);
#endif
if (tzn != NULL)
*tzn = tzname[(tm->tm_isdst > 0)];
#else
#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
#endif
#else /* !USE_POSIX_TIME */
*tzp = CTimeZone; /* V7 conventions; don't know timezone? */
if (tzn != NULL)
*tzn = CTZName;
#endif
/* otherwise, outside of timezone range so convert to GMT... */
}
else
{
*tzp = 0;
tm->tm_isdst = 0;
if (tzn != NULL)
*tzn = NULL;
}
return 0;
} /* date2tm() */
/***************************************************************************** /*****************************************************************************
* Time ADT * Time ADT
*****************************************************************************/ *****************************************************************************/
...@@ -906,19 +846,8 @@ datetimetz_timestamp(PG_FUNCTION_ARGS) ...@@ -906,19 +846,8 @@ datetimetz_timestamp(PG_FUNCTION_ARGS)
DateADT date = PG_GETARG_DATEADT(0); DateADT date = PG_GETARG_DATEADT(0);
TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1);
Timestamp result; Timestamp result;
struct tm tt,
*tm = &tt;
int tz;
double fsec = 0;
char *tzn;
if (date2tm(date, &tz, tm, &fsec, &tzn) != 0)
elog(ERROR, "Unable to convert date to timestamp");
if (tm2timestamp(tm, fsec, &time->zone, &result) != 0)
elog(ERROR, "Timestamp out of range");
result += time->time; result = date*86400.0 + time->time + time->zone;
PG_RETURN_TIMESTAMP(result); PG_RETURN_TIMESTAMP(result);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.52 2000/07/14 15:33:33 thomas Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.53 2000/09/12 05:41:37 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2247,8 +2247,8 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str) ...@@ -2247,8 +2247,8 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
sprintf(cp, "%s%02d:%02d", (is_nonzero ? " " : ""), sprintf(cp, "%s%02d:%02d", (is_nonzero ? " " : ""),
abs(tm->tm_hour), abs(tm->tm_min)); abs(tm->tm_hour), abs(tm->tm_min));
cp += strlen(cp); cp += strlen(cp);
if ((tm->tm_hour != 0) || (tm->tm_min != 0)) /* Mark as "non-zero" since the fields are now filled in */
is_nonzero = TRUE; is_nonzero = TRUE;
/* fractional seconds? */ /* fractional seconds? */
if (fsec != 0) if (fsec != 0)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment