📄 timestamp.c
字号:
*/ if (attimezone == NULL && HasCTZSet) { *tzp = CTimeZone; tm->tm_isdst = 0; tm->tm_gmtoff = CTimeZone; tm->tm_zone = NULL; if (tzn != NULL) *tzn = NULL; return 0; } /* * If the time falls within the range of pg_time_t, use pg_localtime() to * rotate to the local time zone. * * First, convert to an integral timestamp, avoiding possibly * platform-specific roundoff-in-wrong-direction errors, and adjust to * Unix epoch. Then see if we can convert to pg_time_t without loss. This * coding avoids hardwiring any assumptions about the width of pg_time_t, * so it should behave sanely on machines without int64. */#ifdef HAVE_INT64_TIMESTAMP dt = (dt - *fsec) / USECS_PER_SEC + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;#else dt = rint(dt - *fsec + (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);#endif utime = (pg_time_t) dt; if ((Timestamp) utime == dt) { struct pg_tm *tx = pg_localtime(&utime, attimezone ? attimezone : global_timezone); tm->tm_year = tx->tm_year + 1900; tm->tm_mon = tx->tm_mon + 1; tm->tm_mday = tx->tm_mday; tm->tm_hour = tx->tm_hour; tm->tm_min = tx->tm_min; tm->tm_sec = tx->tm_sec; tm->tm_isdst = tx->tm_isdst; tm->tm_gmtoff = tx->tm_gmtoff; tm->tm_zone = tx->tm_zone; *tzp = -tm->tm_gmtoff; if (tzn != NULL) *tzn = (char *) tm->tm_zone; } else { /* * When out of range of pg_time_t, treat as GMT */ *tzp = 0; /* Mark this as *no* time zone available */ tm->tm_isdst = -1; tm->tm_gmtoff = 0; tm->tm_zone = NULL; if (tzn != NULL) *tzn = NULL; } return 0;}/* tm2timestamp() * Convert a tm structure to a timestamp data type. * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * * Returns -1 on failure (value out of range). */inttm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *result){#ifdef HAVE_INT64_TIMESTAMP int date; int64 time;#else double date, time;#endif /* Julian day routines are not correct for negative Julian days */ if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday)) return -1; date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);#ifdef HAVE_INT64_TIMESTAMP *result = date * USECS_PER_DAY + time; /* check for major overflow */ if ((*result - time) / USECS_PER_DAY != date) return -1; /* check for just-barely overflow (okay except time-of-day wraps) */ if ((*result < 0 && date >= 0) || (*result >= 0 && date < 0)) return -1;#else *result = date * SECS_PER_DAY + time;#endif if (tzp != NULL) *result = dt2local(*result, -(*tzp)); return 0;}/* interval2tm() * Convert a interval data type to a tm structure. */intinterval2tm(Interval span, struct pg_tm * tm, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP int64 time; int64 tfrac;#else double time; double tfrac;#endif tm->tm_year = span.month / MONTHS_PER_YEAR; tm->tm_mon = span.month % MONTHS_PER_YEAR; tm->tm_mday = span.day; time = span.time;#ifdef HAVE_INT64_TIMESTAMP tfrac = time / USECS_PER_HOUR; time -= tfrac * USECS_PER_HOUR; tm->tm_hour = tfrac; /* could overflow ... */ tfrac = time / USECS_PER_MINUTE; time -= tfrac * USECS_PER_MINUTE; tm->tm_min = tfrac; tfrac = time / USECS_PER_SEC; *fsec = time - (tfrac * USECS_PER_SEC); tm->tm_sec = tfrac;#elserecalc: TMODULO(time, tfrac, (double) SECS_PER_HOUR); tm->tm_hour = tfrac; /* could overflow ... */ TMODULO(time, tfrac, (double) SECS_PER_MINUTE); tm->tm_min = tfrac; TMODULO(time, tfrac, 1.0); tm->tm_sec = tfrac; time = TSROUND(time); /* roundoff may need to propagate to higher-order fields */ if (time >= 1.0) { time = ceil(span.time); goto recalc; } *fsec = time;#endif return 0;}inttm2interval(struct pg_tm * tm, fsec_t fsec, Interval *span){ span->month = tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon; span->day = tm->tm_mday;#ifdef HAVE_INT64_TIMESTAMP span->time = (((((tm->tm_hour * INT64CONST(60)) + tm->tm_min) * INT64CONST(60)) + tm->tm_sec) * USECS_PER_SEC) + fsec;#else span->time = (((tm->tm_hour * (double) MINS_PER_HOUR) + tm->tm_min) * (double) SECS_PER_MINUTE) + tm->tm_sec + fsec;#endif return 0;}#ifdef HAVE_INT64_TIMESTAMPstatic int64time2t(const int hour, const int min, const int sec, const fsec_t fsec){ return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;} /* time2t() */#elsestatic doubletime2t(const int hour, const int min, const int sec, const fsec_t fsec){ return (((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec + fsec;} /* time2t() */#endifstatic Timestampdt2local(Timestamp dt, int tz){#ifdef HAVE_INT64_TIMESTAMP dt -= (tz * USECS_PER_SEC);#else dt -= tz;#endif return dt;} /* dt2local() *//***************************************************************************** * PUBLIC ROUTINES * *****************************************************************************/Datumtimestamp_finite(PG_FUNCTION_ARGS){ Timestamp timestamp = PG_GETARG_TIMESTAMP(0); PG_RETURN_BOOL(!TIMESTAMP_NOT_FINITE(timestamp));}Datuminterval_finite(PG_FUNCTION_ARGS){ PG_RETURN_BOOL(true);}/*---------------------------------------------------------- * Relational operators for timestamp. *---------------------------------------------------------*/voidGetEpochTime(struct pg_tm * tm){ struct pg_tm *t0; pg_time_t epoch = 0; t0 = pg_gmtime(&epoch); tm->tm_year = t0->tm_year; tm->tm_mon = t0->tm_mon; tm->tm_mday = t0->tm_mday; tm->tm_hour = t0->tm_hour; tm->tm_min = t0->tm_min; tm->tm_sec = t0->tm_sec; tm->tm_year += 1900; tm->tm_mon++;}TimestampSetEpochTimestamp(void){ Timestamp dt; struct pg_tm tt, *tm = &tt; GetEpochTime(tm); /* we don't bother to test for failure ... */ tm2timestamp(tm, 0, NULL, &dt); return dt;} /* SetEpochTimestamp() *//* * We are currently sharing some code between timestamp and timestamptz. * The comparison functions are among them. - thomas 2001-09-25 * * timestamp_relop - is timestamp1 relop timestamp2 * * collate invalid timestamp at the end */inttimestamp_cmp_internal(Timestamp dt1, Timestamp dt2){#ifdef HAVE_INT64_TIMESTAMP return (dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0);#else /* * When using float representation, we have to be wary of NaNs. * * We consider all NANs to be equal and larger than any non-NAN. This is * somewhat arbitrary; the important thing is to have a consistent sort * order. */ if (isnan(dt1)) { if (isnan(dt2)) return 0; /* NAN = NAN */ else return 1; /* NAN > non-NAN */ } else if (isnan(dt2)) { return -1; /* non-NAN < NAN */ } else { if (dt1 > dt2) return 1; else if (dt1 < dt2) return -1; else return 0; }#endif}Datumtimestamp_eq(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);}Datumtimestamp_ne(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);}Datumtimestamp_lt(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);}Datumtimestamp_gt(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);}Datumtimestamp_le(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);}Datumtimestamp_ge(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);}Datumtimestamp_cmp(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));}/* * Crosstype comparison functions for timestamp vs timestamptz */Datumtimestamp_eq_timestamptz(PG_FUNCTION_ARGS){ Timestamp timestampVal = PG_GETARG_TIMESTAMP(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);}Datumtimestamp_ne_timestamptz(PG_FUNCTION_ARGS){ Timestamp timestampVal = PG_GETARG_TIMESTAMP(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);}Datumtimestamp_lt_timestamptz(PG_FUNCTION_ARGS){ Timestamp timestampVal = PG_GETARG_TIMESTAMP(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);}Datumtimestamp_gt_timestamptz(PG_FUNCTION_ARGS){ Timestamp timestampVal = PG_GETARG_TIMESTAMP(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);}Datumtimestamp_le_timestamptz(PG_FUNCTION_ARGS){ Timestamp timestampVal = PG_GETARG_TIMESTAMP(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);}Datumtimestamp_ge_timestamptz(PG_FUNCTION_ARGS){ Timestamp timestampVal = PG_GETARG_TIMESTAMP(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);}Datumtimestamp_cmp_timestamptz(PG_FUNCTION_ARGS){ Timestamp timestampVal = PG_GETARG_TIMESTAMP(0); TimestampTz dt2 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz dt1; dt1 = timestamp2timestamptz(timestampVal); PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));}Datumtimestamptz_eq_timestamp(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); Timestamp timestampVal = PG_GETARG_TIMESTAMP(1); TimestampTz dt2; dt2 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);}Datumtimestamptz_ne_timestamp(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); Timestamp timestampVal = PG_GETARG_TIMESTAMP(1); TimestampTz dt2; dt2 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);}Datumtimestamptz_lt_timestamp(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); Timestamp timestampVal = PG_GETARG_TIMESTAMP(1); TimestampTz dt2; dt2 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);}Datumtimestamptz_gt_timestamp(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); Timestamp timestampVal = PG_GETARG_TIMESTAMP(1); TimestampTz dt2; dt2 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);}Datumtimestamptz_le_timestamp(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); Timestamp timestampVal = PG_GETARG_TIMESTAMP(1); TimestampTz dt2; dt2 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);}Datumtimestamptz_ge_timestamp(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); Timestamp timestampVal = PG_GETARG_TIMESTAMP(1); TimestampTz dt2; dt2 = timestamp2timestamptz(timestampVal); PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);}Datumtimestamptz_cmp_timestamp(PG_FUNCTION_ARGS){ TimestampTz dt1 = PG_GETARG_TIMESTAMPTZ(0); Timestamp timestampVal = PG_GETARG_TIMESTAMP(1); TimestampTz dt2; dt2 = timestamp2timestamptz(timestampVal); PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));}/* * interval_relop - is interval1 relop interval2 * * collate invalid interval at the end */static intinterval_cmp_internal(Interval *interval1, Interval *interval2){#ifdef HAVE_INT64_TIMESTAMP int64 span1, span2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -