summaryrefslogtreecommitdiff
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.c238
1 files changed, 120 insertions, 118 deletions
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c
index e6f4689a59f..186522148d5 100644
--- a/src/backend/utils/adt/datetime.c
+++ b/src/backend/utils/adt/datetime.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.207 2009/06/10 05:05:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.208 2009/06/11 14:49:03 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,17 +40,17 @@ static int DecodeTime(char *str, int fmask, int range,
int *tmask, struct pg_tm * tm, fsec_t *fsec);
static int DecodeTimezone(char *str, int *tzp);
static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
-static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
- struct pg_tm * tm);
-static int ValidateDate(int fmask, bool is2digits, bool bc,
- struct pg_tm * tm);
+static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
+ struct pg_tm * tm);
+static int ValidateDate(int fmask, bool is2digits, bool bc,
+ struct pg_tm * tm);
static void TrimTrailingZeros(char *str);
static void AppendSeconds(char *cp, int sec, fsec_t fsec,
- int precision, bool fillzeros);
+ int precision, bool fillzeros);
static void AdjustFractSeconds(double frac, struct pg_tm * tm, fsec_t *fsec,
- int scale);
+ int scale);
static void AdjustFractDays(double frac, struct pg_tm * tm, fsec_t *fsec,
- int scale);
+ int scale);
const int day_tab[2][13] =
@@ -266,7 +266,7 @@ static const datetkn *deltacache[MAXDATEFIELDS] = {NULL};
static int
strtoi(const char *nptr, char **endptr, int base)
{
- long val;
+ long val;
val = strtol(nptr, endptr, base);
#ifdef HAVE_LONG_INT_64
@@ -461,8 +461,8 @@ static void
AppendTimestampSeconds(char *cp, struct pg_tm * tm, fsec_t fsec)
{
/*
- * In float mode, don't print fractional seconds before 1 AD,
- * since it's unlikely there's any precision left ...
+ * In float mode, don't print fractional seconds before 1 AD, since it's
+ * unlikely there's any precision left ...
*/
#ifndef HAVE_INT64_TIMESTAMP
if (tm->tm_year <= 0)
@@ -478,18 +478,18 @@ AppendTimestampSeconds(char *cp, struct pg_tm * tm, fsec_t fsec)
static void
AdjustFractSeconds(double frac, struct pg_tm * tm, fsec_t *fsec, int scale)
{
- int sec;
+ int sec;
if (frac == 0)
return;
- frac *= scale;
- sec = (int) frac;
+ frac *= scale;
+ sec = (int) frac;
tm->tm_sec += sec;
- frac -= sec;
+ frac -= sec;
#ifdef HAVE_INT64_TIMESTAMP
- *fsec += rint(frac * 1000000);
+ *fsec += rint(frac * 1000000);
#else
- *fsec += frac;
+ *fsec += frac;
#endif
}
@@ -497,14 +497,14 @@ AdjustFractSeconds(double frac, struct pg_tm * tm, fsec_t *fsec, int scale)
static void
AdjustFractDays(double frac, struct pg_tm * tm, fsec_t *fsec, int scale)
{
- int extra_days;
+ int extra_days;
if (frac == 0)
return;
- frac *= scale;
- extra_days = (int) frac;
+ frac *= scale;
+ extra_days = (int) frac;
tm->tm_mday += extra_days;
- frac -= extra_days;
+ frac -= extra_days;
AdjustFractSeconds(frac, tm, fsec, SECS_PER_DAY);
}
@@ -1358,7 +1358,7 @@ DecodeDateTime(char **field, int *ftype, int nf,
if (tmask & fmask)
return DTERR_BAD_FORMAT;
fmask |= tmask;
- } /* end loop over fields */
+ } /* end loop over fields */
/* do final checking/adjustment of Y/M/D fields */
dterr = ValidateDate(fmask, is2digits, bc, tm);
@@ -2042,7 +2042,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
if (tmask & fmask)
return DTERR_BAD_FORMAT;
fmask |= tmask;
- } /* end loop over fields */
+ } /* end loop over fields */
/* do final checking/adjustment of Y/M/D fields */
dterr = ValidateDate(fmask, is2digits, bc, tm);
@@ -2059,7 +2059,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
tm->tm_sec < 0 || tm->tm_sec > 60 || tm->tm_hour > 24 ||
- /* test for > 24:00:00 */
+ /* test for > 24:00:00 */
(tm->tm_hour == 24 &&
(tm->tm_min > 0 || tm->tm_sec > 0 || *fsec > 0)) ||
#ifdef HAVE_INT64_TIMESTAMP
@@ -2262,7 +2262,7 @@ ValidateDate(int fmask, bool is2digits, bool bc, struct pg_tm * tm)
else if (is2digits)
{
/* process 1 or 2-digit input as 1970-2069 AD, allow '0' and '00' */
- if (tm->tm_year < 0) /* just paranoia */
+ if (tm->tm_year < 0) /* just paranoia */
return DTERR_FIELD_OVERFLOW;
if (tm->tm_year < 70)
tm->tm_year += 2000;
@@ -2599,8 +2599,8 @@ DecodeNumberField(int len, char *str, int fmask,
if ((cp = strchr(str, '.')) != NULL)
{
/*
- * Can we use ParseFractionalSecond here? Not clear whether
- * trailing junk should be rejected ...
+ * Can we use ParseFractionalSecond here? Not clear whether trailing
+ * junk should be rejected ...
*/
double frac;
@@ -2805,16 +2805,16 @@ DecodeSpecial(int field, char *lowtoken, int *val)
*
* Zero out a pg_tm and associated fsec_t
*/
-static inline void
-ClearPgTm(struct pg_tm *tm, fsec_t *fsec)
+static inline void
+ClearPgTm(struct pg_tm * tm, fsec_t *fsec)
{
tm->tm_year = 0;
- tm->tm_mon = 0;
+ tm->tm_mon = 0;
tm->tm_mday = 0;
tm->tm_hour = 0;
- tm->tm_min = 0;
- tm->tm_sec = 0;
- *fsec = 0;
+ tm->tm_min = 0;
+ tm->tm_sec = 0;
+ *fsec = 0;
}
@@ -2845,7 +2845,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
*dtype = DTK_DELTA;
type = IGNORE_DTF;
- ClearPgTm(tm,fsec);
+ ClearPgTm(tm, fsec);
/* read through list backwards to pick up units before values */
for (i = nf - 1; i >= 0; i--)
@@ -2863,16 +2863,16 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
case DTK_TZ:
/*
- * Timezone is a token with a leading sign character and
- * at least one digit; there could be ':', '.', '-'
- * embedded in it as well.
+ * Timezone is a token with a leading sign character and at
+ * least one digit; there could be ':', '.', '-' embedded in
+ * it as well.
*/
Assert(*field[i] == '-' || *field[i] == '+');
/*
* Try for hh:mm or hh:mm:ss. If not, fall through to
- * DTK_NUMBER case, which can handle signed float numbers
- * and signed year-month values.
+ * DTK_NUMBER case, which can handle signed float numbers and
+ * signed year-month values.
*/
if (strchr(field[i] + 1, ':') != NULL &&
DecodeTime(field[i] + 1, fmask, INTERVAL_FULL_RANGE,
@@ -2944,7 +2944,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
if (*cp == '-')
{
/* SQL "years-months" syntax */
- int val2;
+ int val2;
val2 = strtoi(cp + 1, &cp, 10);
if (errno == ERANGE || val2 < 0 || val2 >= MONTHS_PER_YEAR)
@@ -3022,7 +3022,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
tm->tm_hour += val;
AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
tmask = DTK_M(HOUR);
- type = DTK_DAY; /* set for next field */
+ type = DTK_DAY; /* set for next field */
break;
case DTK_DAY:
@@ -3133,7 +3133,7 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
/*----------
* The SQL standard defines the interval literal
- * '-1 1:00:00'
+ * '-1 1:00:00'
* to mean "negative 1 days and negative 1 hours", while Postgres
* traditionally treats this as meaning "negative 1 days and positive
* 1 hours". In SQL_STANDARD intervalstyle, we apply the leading sign
@@ -3143,14 +3143,14 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
* This protects us against misinterpreting postgres-style dump output,
* since the postgres-style output code has always put an explicit sign on
* all fields following a negative field. But note that SQL-spec output
- * is ambiguous and can be misinterpreted on load! (So it's best practice
+ * is ambiguous and can be misinterpreted on load! (So it's best practice
* to dump in postgres style, not SQL style.)
*----------
*/
if (IntervalStyle == INTSTYLE_SQL_STANDARD && *field[0] == '-')
{
/* Check for additional explicit signs */
- bool more_signs = false;
+ bool more_signs = false;
for (i = 1; i < nf; i++)
{
@@ -3164,8 +3164,8 @@ DecodeInterval(char **field, int *ftype, int nf, int range,
if (!more_signs)
{
/*
- * Rather than re-determining which field was field[0], just
- * force 'em all negative.
+ * Rather than re-determining which field was field[0], just force
+ * 'em all negative.
*/
if (*fsec > 0)
*fsec = -(*fsec);
@@ -3245,28 +3245,28 @@ ISO8601IntegerWidth(char *fieldstart)
/* DecodeISO8601Interval()
- * Decode an ISO 8601 time interval of the "format with designators"
- * (section 4.4.3.2) or "alternative format" (section 4.4.3.3)
- * Examples: P1D for 1 day
- * PT1H for 1 hour
- * P2Y6M7DT1H30M for 2 years, 6 months, 7 days 1 hour 30 min
- * P0002-06-07T01:30:00 the same value in alternative format
+ * Decode an ISO 8601 time interval of the "format with designators"
+ * (section 4.4.3.2) or "alternative format" (section 4.4.3.3)
+ * Examples: P1D for 1 day
+ * PT1H for 1 hour
+ * P2Y6M7DT1H30M for 2 years, 6 months, 7 days 1 hour 30 min
+ * P0002-06-07T01:30:00 the same value in alternative format
*
* Returns 0 if successful, DTERR code if bogus input detected.
* Note: error code should be DTERR_BAD_FORMAT if input doesn't look like
* ISO8601, otherwise this could cause unexpected error messages.
* dtype, tm, fsec are output parameters.
*
- * A couple exceptions from the spec:
- * - a week field ('W') may coexist with other units
- * - allows decimals in fields other than the least significant unit.
+ * A couple exceptions from the spec:
+ * - a week field ('W') may coexist with other units
+ * - allows decimals in fields other than the least significant unit.
*/
int
DecodeISO8601Interval(char *str,
int *dtype, struct pg_tm * tm, fsec_t *fsec)
{
- bool datepart = true;
- bool havefield = false;
+ bool datepart = true;
+ bool havefield = false;
*dtype = DTK_DELTA;
ClearPgTm(tm, fsec);
@@ -3277,13 +3277,13 @@ DecodeISO8601Interval(char *str,
str++;
while (*str)
{
- char *fieldstart;
- int val;
- double fval;
- char unit;
- int dterr;
+ char *fieldstart;
+ int val;
+ double fval;
+ char unit;
+ int dterr;
- if (*str == 'T') /* T indicates the beginning of the time part */
+ if (*str == 'T') /* T indicates the beginning of the time part */
{
datepart = false;
havefield = false;
@@ -3297,14 +3297,14 @@ DecodeISO8601Interval(char *str,
return dterr;
/*
- * Note: we could step off the end of the string here. Code below
+ * Note: we could step off the end of the string here. Code below
* *must* exit the loop if unit == '\0'.
*/
unit = *str++;
if (datepart)
{
- switch (unit) /* before T: Y M W D */
+ switch (unit) /* before T: Y M W D */
{
case 'Y':
tm->tm_year += val;
@@ -3322,12 +3322,12 @@ DecodeISO8601Interval(char *str,
tm->tm_mday += val;
AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
break;
- case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
+ case 'T': /* ISO 8601 4.4.3.3 Alternative Format / Basic */
case '\0':
if (ISO8601IntegerWidth(fieldstart) == 8 && !havefield)
{
tm->tm_year += val / 10000;
- tm->tm_mon += (val / 100) % 100;
+ tm->tm_mon += (val / 100) % 100;
tm->tm_mday += val % 100;
AdjustFractSeconds(fval, tm, fsec, SECS_PER_DAY);
if (unit == '\0')
@@ -3337,12 +3337,13 @@ DecodeISO8601Interval(char *str,
continue;
}
/* Else fall through to extended alternative format */
- case '-': /* ISO 8601 4.4.3.3 Alternative Format, Extended */
+ case '-': /* ISO 8601 4.4.3.3 Alternative Format,
+ * Extended */
if (havefield)
return DTERR_BAD_FORMAT;
tm->tm_year += val;
- tm->tm_mon += (fval * 12);
+ tm->tm_mon += (fval * 12);
if (unit == '\0')
return 0;
if (unit == 'T')
@@ -3355,7 +3356,7 @@ DecodeISO8601Interval(char *str,
dterr = ParseISO8601Number(str, &str, &val, &fval);
if (dterr)
return dterr;
- tm->tm_mon += val;
+ tm->tm_mon += val;
AdjustFractDays(fval, tm, fsec, DAYS_PER_MONTH);
if (*str == '\0')
return 0;
@@ -3368,7 +3369,7 @@ DecodeISO8601Interval(char *str,
if (*str != '-')
return DTERR_BAD_FORMAT;
str++;
-
+
dterr = ParseISO8601Number(str, &str, &val, &fval);
if (dterr)
return dterr;
@@ -3390,7 +3391,7 @@ DecodeISO8601Interval(char *str,
}
else
{
- switch (unit) /* after T: H M S */
+ switch (unit) /* after T: H M S */
{
case 'H':
tm->tm_hour += val;
@@ -3404,17 +3405,18 @@ DecodeISO8601Interval(char *str,
tm->tm_sec += val;
AdjustFractSeconds(fval, tm, fsec, 1);
break;
- case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
- if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
+ case '\0': /* ISO 8601 4.4.3.3 Alternative Format */
+ if (ISO8601IntegerWidth(fieldstart) == 6 && !havefield)
{
tm->tm_hour += val / 10000;
- tm->tm_min += (val / 100) % 100;
- tm->tm_sec += val % 100;
+ tm->tm_min += (val / 100) % 100;
+ tm->tm_sec += val % 100;
AdjustFractSeconds(fval, tm, fsec, 1);
return 0;
}
/* Else fall through to extended alternative format */
- case ':': /* ISO 8601 4.4.3.3 Alternative Format, Extended */
+ case ':': /* ISO 8601 4.4.3.3 Alternative Format,
+ * Extended */
if (havefield)
return DTERR_BAD_FORMAT;
@@ -3422,22 +3424,22 @@ DecodeISO8601Interval(char *str,
AdjustFractSeconds(fval, tm, fsec, SECS_PER_HOUR);
if (unit == '\0')
return 0;
-
+
dterr = ParseISO8601Number(str, &str, &val, &fval);
if (dterr)
return dterr;
- tm->tm_min += val;
+ tm->tm_min += val;
AdjustFractSeconds(fval, tm, fsec, SECS_PER_MINUTE);
if (*str == '\0')
return 0;
if (*str != ':')
return DTERR_BAD_FORMAT;
str++;
-
+
dterr = ParseISO8601Number(str, &str, &val, &fval);
if (dterr)
return dterr;
- tm->tm_sec += val;
+ tm->tm_sec += val;
AdjustFractSeconds(fval, tm, fsec, 1);
if (*str == '\0')
return 0;
@@ -3843,9 +3845,10 @@ AddPostgresIntPart(char *cp, int value, const char *units,
value,
units,
(value != 1) ? "s" : "");
+
/*
- * Each nonzero field sets is_before for (only) the next one. This is
- * a tad bizarre but it's how it worked before...
+ * Each nonzero field sets is_before for (only) the next one. This is a
+ * tad bizarre but it's how it worked before...
*/
*is_before = (value < 0);
*is_zero = FALSE;
@@ -3884,7 +3887,7 @@ AddVerboseIntPart(char *cp, int value, const char *units,
* Actually, afaik, ISO 8601 does specify formats for "time
* intervals...[of the]...format with time-unit designators", which
* are pretty ugly. The format looks something like
- * P1Y1M1DT1H1M1.12345S
+ * P1Y1M1DT1H1M1.12345S
* but useful for exchanging data with computers instead of humans.
* - ron 2003-07-14
*
@@ -3897,11 +3900,11 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
{
char *cp = str;
int year = tm->tm_year;
- int mon = tm->tm_mon;
+ int mon = tm->tm_mon;
int mday = tm->tm_mday;
int hour = tm->tm_hour;
- int min = tm->tm_min;
- int sec = tm->tm_sec;
+ int min = tm->tm_min;
+ int sec = tm->tm_sec;
bool is_before = FALSE;
bool is_zero = TRUE;
@@ -3913,21 +3916,21 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
*/
switch (style)
{
- /* SQL Standard interval format */
+ /* SQL Standard interval format */
case INTSTYLE_SQL_STANDARD:
{
- bool has_negative = year < 0 || mon < 0 ||
- mday < 0 || hour < 0 ||
- min < 0 || sec < 0 || fsec < 0;
- bool has_positive = year > 0 || mon > 0 ||
- mday > 0 || hour > 0 ||
- min > 0 || sec > 0 || fsec > 0;
- bool has_year_month = year != 0 || mon != 0;
- bool has_day_time = mday != 0 || hour != 0 ||
- min != 0 || sec != 0 || fsec != 0;
- bool has_day = mday != 0;
- bool sql_standard_value = !(has_negative && has_positive) &&
- !(has_year_month && has_day_time);
+ bool has_negative = year < 0 || mon < 0 ||
+ mday < 0 || hour < 0 ||
+ min < 0 || sec < 0 || fsec < 0;
+ bool has_positive = year > 0 || mon > 0 ||
+ mday > 0 || hour > 0 ||
+ min > 0 || sec > 0 || fsec > 0;
+ bool has_year_month = year != 0 || mon != 0;
+ bool has_day_time = mday != 0 || hour != 0 ||
+ min != 0 || sec != 0 || fsec != 0;
+ bool has_day = mday != 0;
+ bool sql_standard_value = !(has_negative && has_positive) &&
+ !(has_year_month && has_day_time);
/*
* SQL Standard wants only 1 "<sign>" preceding the whole
@@ -3937,11 +3940,11 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
{
*cp++ = '-';
year = -year;
- mon = -mon;
+ mon = -mon;
mday = -mday;
hour = -hour;
- min = -min;
- sec = -sec;
+ min = -min;
+ sec = -sec;
fsec = -fsec;
}
@@ -3952,15 +3955,14 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
else if (!sql_standard_value)
{
/*
- * For non sql-standard interval values,
- * force outputting the signs to avoid
- * ambiguities with intervals with mixed
- * sign components.
+ * For non sql-standard interval values, force outputting
+ * the signs to avoid ambiguities with intervals with
+ * mixed sign components.
*/
- char year_sign = (year < 0 || mon < 0) ? '-' : '+';
- char day_sign = (mday < 0) ? '-' : '+';
- char sec_sign = (hour < 0 || min < 0 ||
- sec < 0 || fsec < 0) ? '-' : '+';
+ char year_sign = (year < 0 || mon < 0) ? '-' : '+';
+ char day_sign = (mday < 0) ? '-' : '+';
+ char sec_sign = (hour < 0 || min < 0 ||
+ sec < 0 || fsec < 0) ? '-' : '+';
sprintf(cp, "%c%d-%d %c%d %c%d:%02d:",
year_sign, abs(year), abs(mon),
@@ -3988,23 +3990,23 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
}
break;
- /* ISO 8601 "time-intervals by duration only" */
+ /* ISO 8601 "time-intervals by duration only" */
case INTSTYLE_ISO_8601:
/* special-case zero to avoid printing nothing */
if (year == 0 && mon == 0 && mday == 0 &&
- hour == 0 && min == 0 && sec == 0 && fsec == 0)
+ hour == 0 && min == 0 && sec == 0 && fsec == 0)
{
sprintf(cp, "PT0S");
break;
}
*cp++ = 'P';
cp = AddISO8601IntPart(cp, year, 'Y');
- cp = AddISO8601IntPart(cp, mon , 'M');
+ cp = AddISO8601IntPart(cp, mon, 'M');
cp = AddISO8601IntPart(cp, mday, 'D');
if (hour != 0 || min != 0 || sec != 0 || fsec != 0)
*cp++ = 'T';
cp = AddISO8601IntPart(cp, hour, 'H');
- cp = AddISO8601IntPart(cp, min , 'M');
+ cp = AddISO8601IntPart(cp, min, 'M');
if (sec != 0 || fsec != 0)
{
if (sec < 0 || fsec < 0)
@@ -4016,14 +4018,14 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
}
break;
- /* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
+ /* Compatible with postgresql < 8.4 when DateStyle = 'iso' */
case INTSTYLE_POSTGRES:
cp = AddPostgresIntPart(cp, year, "year", &is_zero, &is_before);
cp = AddPostgresIntPart(cp, mon, "mon", &is_zero, &is_before);
cp = AddPostgresIntPart(cp, mday, "day", &is_zero, &is_before);
if (is_zero || hour != 0 || min != 0 || sec != 0 || fsec != 0)
{
- bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
+ bool minus = (hour < 0 || min < 0 || sec < 0 || fsec < 0);
sprintf(cp, "%s%s%02d:%02d:",
is_zero ? "" : " ",
@@ -4034,7 +4036,7 @@ EncodeInterval(struct pg_tm * tm, fsec_t fsec, int style, char *str)
}
break;
- /* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
+ /* Compatible with postgresql < 8.4 when DateStyle != 'iso' */
case INTSTYLE_POSTGRES_VERBOSE:
default:
strcpy(cp, "@");