aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/datetime.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/datetime.c')
-rw-r--r--src/backend/utils/adt/datetime.c230
1 files changed, 120 insertions, 110 deletions
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index 33fa7647ed5..275231983ee 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.72 2001/10/11 18:06:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.73 2001/10/18 17:30:15 thomas Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,6 +38,7 @@ static int DecodeTimezone(char *str, int *tzp);
static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel);
static int DecodeDate(char *str, int fmask, int *tmask, struct tm * tm);
static int DecodePosixTimezone(char *str, int *val);
+void TrimTrailingZeros(char *str);
int day_tab[2][13] = {
@@ -239,81 +240,73 @@ static unsigned int australian_szdatetktbl = sizeof australian_datetktbl /
sizeof australian_datetktbl[0];
static datetkn deltatktbl[] = {
-/* text, token, lexval */
- {"@", IGNORE, 0}, /* postgres relative time prefix */
+ /* text, token, lexval */
+ {"@", IGNORE, 0}, /* postgres relative prefix */
{DAGO, AGO, 0}, /* "ago" indicates negative time offset */
- {"c", UNITS, DTK_CENTURY}, /* "century" relative time units */
- {"cent", UNITS, DTK_CENTURY}, /* "century" relative time units */
- {"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative time units */
- {DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative time units */
- {"d", UNITS, DTK_DAY}, /* "day" relative time units */
- {DDAY, UNITS, DTK_DAY}, /* "day" relative time units */
- {"days", UNITS, DTK_DAY}, /* "days" relative time units */
- {"dec", UNITS, DTK_DECADE}, /* "decade" relative time units */
- {"decs", UNITS, DTK_DECADE},/* "decades" relative time units */
- {DDECADE, UNITS, DTK_DECADE}, /* "decade" relative time units */
- {"decades", UNITS, DTK_DECADE}, /* "decades" relative time units */
- {"h", UNITS, DTK_HOUR}, /* "hour" relative time units */
- {DHOUR, UNITS, DTK_HOUR}, /* "hour" relative time units */
- {"hours", UNITS, DTK_HOUR}, /* "hours" relative time units */
- {"hr", UNITS, DTK_HOUR}, /* "hour" relative time units */
- {"hrs", UNITS, DTK_HOUR}, /* "hours" relative time units */
+ {"c", UNITS, DTK_CENTURY}, /* "century" relative */
+ {"cent", UNITS, DTK_CENTURY}, /* "century" relative */
+ {"centuries", UNITS, DTK_CENTURY}, /* "centuries" relative */
+ {DCENTURY, UNITS, DTK_CENTURY}, /* "century" relative */
+ {"d", UNITS, DTK_DAY}, /* "day" relative */
+ {DDAY, UNITS, DTK_DAY}, /* "day" relative */
+ {"days", UNITS, DTK_DAY}, /* "days" relative */
+ {"dec", UNITS, DTK_DECADE}, /* "decade" relative */
+ {"decs", UNITS, DTK_DECADE}, /* "decades" relative */
+ {DDECADE, UNITS, DTK_DECADE}, /* "decade" relative */
+ {"decades", UNITS, DTK_DECADE}, /* "decades" relative */
+ {"h", UNITS, DTK_HOUR}, /* "hour" relative */
+ {DHOUR, UNITS, DTK_HOUR}, /* "hour" relative */
+ {"hours", UNITS, DTK_HOUR}, /* "hours" relative */
+ {"hr", UNITS, DTK_HOUR}, /* "hour" relative */
+ {"hrs", UNITS, DTK_HOUR}, /* "hours" relative */
{INVALID, RESERV, DTK_INVALID}, /* reserved for invalid time */
- {"m", UNITS, DTK_MINUTE}, /* "minute" relative time units */
- {"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative
- * time units */
- {"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative time
- * units */
- {"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative time units */
- {"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative
- * time units */
- {DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative
- * time units */
- {"millisecon", UNITS, DTK_MILLISEC}, /* relative time units */
- {"min", UNITS, DTK_MINUTE}, /* "minute" relative time units */
- {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
- {"mins", UNITS, DTK_MINUTE},/* "minutes" relative time units */
- {DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative time units */
- {"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative time units */
- {"mon", UNITS, DTK_MONTH}, /* "months" relative time units */
- {"mons", UNITS, DTK_MONTH}, /* "months" relative time units */
- {DMONTH, UNITS, DTK_MONTH}, /* "month" relative time units */
+ {"m", UNITS, DTK_MINUTE}, /* "minute" relative */
+ {"microsecon", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {"mil", UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
+ {"millennia", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
+ {DMILLENNIUM, UNITS, DTK_MILLENNIUM}, /* "millennium" relative */
+ {"millisecon", UNITS, DTK_MILLISEC}, /* relative */
+ {"mils", UNITS, DTK_MILLENNIUM}, /* "millennia" relative */
+ {"min", UNITS, DTK_MINUTE}, /* "minute" relative */
+ {"mins", UNITS, DTK_MINUTE}, /* "minutes" relative */
+ {"mins", UNITS, DTK_MINUTE}, /* "minutes" relative */
+ {DMINUTE, UNITS, DTK_MINUTE}, /* "minute" relative */
+ {"minutes", UNITS, DTK_MINUTE}, /* "minutes" relative */
+ {"mon", UNITS, DTK_MONTH}, /* "months" relative */
+ {"mons", UNITS, DTK_MONTH}, /* "months" relative */
+ {DMONTH, UNITS, DTK_MONTH}, /* "month" relative */
{"months", UNITS, DTK_MONTH},
{"ms", UNITS, DTK_MILLISEC},
{"msec", UNITS, DTK_MILLISEC},
{DMILLISEC, UNITS, DTK_MILLISEC},
{"mseconds", UNITS, DTK_MILLISEC},
{"msecs", UNITS, DTK_MILLISEC},
- {"qtr", UNITS, DTK_QUARTER},/* "quarter" relative time */
- {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative time */
- {"reltime", IGNORE, 0}, /* for pre-v6.1 "Undefined Reltime" */
+ {"qtr", UNITS, DTK_QUARTER}, /* "quarter" relative */
+ {DQUARTER, UNITS, DTK_QUARTER}, /* "quarter" relative */
+ {"reltime", IGNORE, 0}, /* pre-v6.1 "Undefined Reltime" */
{"s", UNITS, DTK_SECOND},
{"sec", UNITS, DTK_SECOND},
{DSECOND, UNITS, DTK_SECOND},
{"seconds", UNITS, DTK_SECOND},
{"secs", UNITS, DTK_SECOND},
- {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
+ {DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */
{"timezone", UNITS, DTK_TZ}, /* "timezone" time offset */
{"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */
{"timezone_m", UNITS, DTK_TZ_MINUTE}, /* timezone minutes units */
{"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */
- {"us", UNITS, DTK_MICROSEC},/* "microsecond" relative time units */
- {"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative time
- * units */
- {DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative time
- * units */
- {"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative time
- * units */
- {"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative time
- * units */
- {"w", UNITS, DTK_WEEK}, /* "week" relative time units */
- {DWEEK, UNITS, DTK_WEEK}, /* "week" relative time units */
- {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative time units */
- {"y", UNITS, DTK_YEAR}, /* "year" relative time units */
- {DYEAR, UNITS, DTK_YEAR}, /* "year" relative time units */
- {"years", UNITS, DTK_YEAR}, /* "years" relative time units */
- {"yr", UNITS, DTK_YEAR}, /* "year" relative time units */
- {"yrs", UNITS, DTK_YEAR}, /* "years" relative time units */
+ {"us", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {"usec", UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {DMICROSEC, UNITS, DTK_MICROSEC}, /* "microsecond" relative */
+ {"useconds", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
+ {"usecs", UNITS, DTK_MICROSEC}, /* "microseconds" relative */
+ {"w", UNITS, DTK_WEEK}, /* "week" relative */
+ {DWEEK, UNITS, DTK_WEEK}, /* "week" relative */
+ {"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */
+ {"y", UNITS, DTK_YEAR}, /* "year" relative */
+ {DYEAR, UNITS, DTK_YEAR}, /* "year" relative */
+ {"years", UNITS, DTK_YEAR}, /* "years" relative */
+ {"yr", UNITS, DTK_YEAR}, /* "year" relative */
+ {"yrs", UNITS, DTK_YEAR}, /* "years" relative */
};
static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];
@@ -346,8 +339,10 @@ date2j(int y, int m, int d)
{
int m12 = (m - 14) / 12;
- return ((1461 * (y + 4800 + m12)) / 4 + (367 * (m - 2 - 12 * (m12))) / 12
- - (3 * ((y + 4900 + m12) / 100)) / 4 + d - 32075);
+ return ((1461 * (y + 4800 + m12)) / 4
+ + (367 * (m - 2 - 12 * (m12))) / 12
+ - (3 * ((y + 4900 + m12) / 100)) / 4
+ + d - 32075);
} /* date2j() */
void
@@ -390,11 +385,28 @@ j2day(int date)
} /* j2day() */
-/*
- * parse and convert date in timestr (the normal interface)
- *
- * Returns the number of seconds since epoch (J2000)
- */
+void
+TrimTrailingZeros(char *str)
+{
+ int len = strlen(str);
+
+ /* chop off trailing one to cope with interval rounding */
+ if (strcmp((str + len - 4), "0001") == 0)
+ {
+ len -= 4;
+ *(str + len) = '\0';
+ }
+
+ /* chop off trailing zeros... */
+ while ((*(str + len - 1) == '0')
+ && (*(str + len - 3) != '.'))
+ {
+ len--;
+ *(str + len) = '\0';
+ }
+ return;
+}
+
/* ParseDateTime()
* Break string into tokens based on a date/time context.
@@ -989,7 +1001,11 @@ DetermineLocalTimeZone(struct tm * tm)
{
int tz;
- if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
+ if (HasCTZSet)
+ {
+ tz = CTimeZone;
+ }
+ else if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
{
#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)
/*
@@ -1044,9 +1060,6 @@ DetermineLocalTimeZone(struct tm * tm)
* SQL92 TIME WITH TIME ZONE, but it reveals
* bogosity with SQL92 date/time standards, since
* we must infer a time zone from current time.
- * XXX Later, we should probably support
- * SET TIME ZONE <integer>
- * which of course is a screwed up convention.
* - thomas 2000-03-10
*/
int
@@ -2246,33 +2259,23 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
sprintf((str + strlen(str)), ":%02.0f", sec);
}
- if ((*tzn != NULL) && (tm->tm_isdst >= 0))
+ /* tzp == NULL indicates that we don't want *any* time zone info in the output string.
+ * *tzn != NULL indicates that we *have* time zone info available.
+ * tm_isdst != -1 indicates that we have a valid time zone translation.
+ */
+ if ((tzp != NULL) && (*tzn != NULL) && (tm->tm_isdst >= 0))
{
- if (tzp != NULL)
- {
- hour = -(*tzp / 3600);
- min = ((abs(*tzp) / 60) % 60);
- }
- else
- {
- hour = 0;
- min = 0;
- }
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
}
-
}
else
{
@@ -2305,12 +2308,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
@@ -2319,6 +2317,13 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+ else if (tzp != NULL)
+ {
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
+ sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+ }
}
else
sprintf((str + 5), "/%04d %02d:%02d %s",
@@ -2341,12 +2346,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
@@ -2355,6 +2355,13 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
if ((*tzn != NULL) && (tm->tm_isdst >= 0))
sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+ else if (tzp != NULL)
+ {
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
+ sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+ }
}
else
sprintf((str + 5), ".%04d %02d:%02d %s",
@@ -2387,12 +2394,7 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
*/
if (fsec != 0) {
sprintf((str + strlen(str)), ":%013.10f", sec);
- /* chop off trailing pairs of zeros... */
- while ((strcmp((str + strlen(str) - 2), "00") == 0)
- && (*(str + strlen(str) - 3) != '.'))
- {
- *(str + strlen(str) - 2) = '\0';
- }
+ TrimTrailingZeros(str);
}
else
{
@@ -2400,8 +2402,16 @@ EncodeDateTime(struct tm * tm, double fsec, int *tzp, char **tzn, int style, cha
}
sprintf((str + strlen(str)), " %04d", tm->tm_year);
- if ((*tzn != NULL) && (tm->tm_isdst >= 0))
+
+ if ((tzp != NULL) && (*tzn != NULL) && (tm->tm_isdst >= 0))
sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn);
+
+ else if (HasCTZSet && (tzp != NULL))
+ {
+ hour = -(*tzp / 3600);
+ min = ((abs(*tzp) / 60) % 60);
+ sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min);
+ }
}
else
{
@@ -2485,12 +2495,12 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
if (fsec != 0)
{
fsec += tm->tm_sec;
- sprintf(cp, ":%05.2f", fabs(fsec));
+ sprintf(cp, ":%013.10f", fabs(fsec));
+ TrimTrailingZeros(cp);
cp += strlen(cp);
is_nonzero = TRUE;
-
- /* otherwise, integer seconds only? */
}
+ /* otherwise, integer seconds only? */
else if (tm->tm_sec != 0)
{
sprintf(cp, ":%02d", abs(tm->tm_sec));