mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
Modify date->timestamp conversion to use mktime().
This should do better than before around Daylight Savings Time transitions.
This commit is contained in:
parent
3bb28381d3
commit
4d745dadc9
@ -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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
result = date*86400.0 + time->time + time->zone;
|
||||||
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;
|
|
||||||
|
|
||||||
PG_RETURN_TIMESTAMP(result);
|
PG_RETURN_TIMESTAMP(result);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|||||||
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user