📄 timestamp.c
字号:
}/* interval2tm() * Convert a interval data type to a tm structure. */intinterval2tm(Interval span, struct tm * tm, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP int64 time;#else double time;#endif if (span.month != 0) { tm->tm_year = span.month / 12; tm->tm_mon = span.month % 12; } else { tm->tm_year = 0; tm->tm_mon = 0; } time = span.time;#ifdef HAVE_INT64_TIMESTAMP tm->tm_mday = (time / INT64CONST(86400000000)); time -= (tm->tm_mday * INT64CONST(86400000000)); tm->tm_hour = (time / INT64CONST(3600000000)); time -= (tm->tm_hour * INT64CONST(3600000000)); tm->tm_min = (time / INT64CONST(60000000)); time -= (tm->tm_min * INT64CONST(60000000)); tm->tm_sec = (time / INT64CONST(1000000)); *fsec = (time - (tm->tm_sec * INT64CONST(1000000)));#else TMODULO(time, tm->tm_mday, 86400e0); TMODULO(time, tm->tm_hour, 3600e0); TMODULO(time, tm->tm_min, 60e0); TMODULO(time, tm->tm_sec, 1e0); *fsec = time;#endif return 0;}inttm2interval(struct tm * tm, fsec_t fsec, Interval *span){ span->month = ((tm->tm_year * 12) + tm->tm_mon);#ifdef HAVE_INT64_TIMESTAMP span->time = ((((((((tm->tm_mday * INT64CONST(24)) + tm->tm_hour) * INT64CONST(60)) + tm->tm_min) * INT64CONST(60)) + tm->tm_sec) * INT64CONST(1000000)) + fsec);#else span->time = ((((((tm->tm_mday * 24.0) + tm->tm_hour) * 60.0) + tm->tm_min) * 60.0) + tm->tm_sec); span->time = JROUND(span->time + fsec);#endif return 0;}#ifdef HAVE_INT64_TIMESTAMPstatic int64time2t(const int hour, const int min, const int sec, const fsec_t fsec){ return ((((((hour * 60) + min) * 60) + sec) * INT64CONST(1000000)) + fsec);} /* time2t() */#elsestatic doubletime2t(const int hour, const int min, const int sec, const fsec_t fsec){ return ((((hour * 60) + min) * 60) + sec + fsec);} /* time2t() */#endifstatic Timestampdt2local(Timestamp dt, int tz){#ifdef HAVE_INT64_TIMESTAMP dt -= (tz * INT64CONST(1000000));#else dt -= tz; dt = JROUND(dt);#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 tm * tm){ struct tm *t0; time_t epoch = 0; t0 = 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; if (tm->tm_year < 1900) tm->tm_year += 1900; tm->tm_mon++; return;} /* GetEpochTime() */TimestampSetEpochTimestamp(void){ Timestamp dt; struct 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 */static 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));}/* * 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;#else double span1, span2;#endif span1 = interval1->time; span2 = interval2->time;#ifdef HAVE_INT64_TIMESTAMP if (interval1->month != 0) span1 += ((interval1->month * INT64CONST(30) * INT64CONST(86400000000))); if (interval2->month != 0) span2 += ((interval2->month * INT64CONST(30) * INT64CONST(86400000000)));#else if (interval1->month != 0) span1 += (interval1->month * (30.0 * 86400)); if (interval2->month != 0) span2 += (interval2->month * (30.0 * 86400));#endif return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0);}Datuminterval_eq(PG_FUNCTION_ARGS){ Interval *interval1 = PG_GETARG_INTERVAL_P(0); Interval *interval2 = PG_GETARG_INTERVAL_P(1); PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) == 0);}Datuminterval_ne(PG_FUNCTION_ARGS){ Interval *interval1 = PG_GETARG_INTERVAL_P(0); Interval *interval2 = PG_GETARG_INTERVAL_P(1); PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) != 0);}Datuminterval_lt(PG_FUNCTION_ARGS){ Interval *interval1 = PG_GETARG_INTERVAL_P(0); Interval *interval2 = PG_GETARG_INTERVAL_P(1); PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) < 0);}Datuminterval_gt(PG_FUNCTION_ARGS){ Interval *interval1 = PG_GETARG_INTERVAL_P(0); Interval *interval2 = PG_GETARG_INTERVAL_P(1); PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) > 0);}Datuminterval_le(PG_FUNCTION_ARGS){ Interval *interval1 = PG_GETARG_INTERVAL_P(0); Interval *interval2 = PG_GETARG_INTERVAL_P(1); PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) <= 0);}Datuminterval_ge(PG_FUNCTION_ARGS){ Interval *interval1 = PG_GETARG_INTERVAL_P(0); Interval *interval2 = PG_GETARG_INTERVAL_P(1); PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);}Datuminterval_cmp(PG_FUNCTION_ARGS){ Interval *interval1 = PG_GETARG_INTERVAL_P(0); Interval *interval2 = PG_GETARG_INTERVAL_P(1); PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));}/* * interval, being an unusual size, needs a specialized hash function. */Datuminterval_hash(PG_FUNCTION_ARGS){ Interval *key = PG_GETARG_INTERVAL_P(0); /* * Specify hash length as sizeof(double) + sizeof(int4), not as * sizeof(Interval), so that any garbage pad bytes in the structure * won't be included in the hash! */ return hash_any((unsigned char *) key, sizeof(key->time) + sizeof(key->month));}/* overlaps_timestamp() --- implements the SQL92 OVERLAPS operator. * * Algorithm is per SQL92 spec. This is much harder than you'd think * because the spec requires us to deliver a non-null answer in some cases * where some of the inputs are null. */Datumoverlaps_timestamp(PG_FUNCTION_ARGS){ /* * The arguments are Timestamps, but we leave them as generic Datums * to avoid unnecessary conversions between value and reference forms * --- not to mention possible dereferences of null pointers. */ Datum ts1 = PG_GETARG_DATUM(0); Datum te1 = PG_GETARG_DATUM(1); Datum ts2 = PG_GETARG_DATUM(2); Datum te2 = PG_GETARG_DATUM(3); bool ts1IsNull = PG_ARGISNULL(0); bool te1IsNull = PG_ARGISNULL(1); bool ts2IsNull = PG_ARGISNULL(2); bool te2IsNull = PG_ARGISNULL(3);#define TIMESTAMP_GT(t1,t2) \ DatumGetBool(DirectFunctionCall2(timestamp_gt,t1,t2))#define TIMESTAMP_LT(t1,t2) \ DatumGetBool(DirectFunctionCall2(timestamp_lt,t1,t2)) /* * If both endpoints of interval 1 are null, the result is null * (unknown). If just one endpoint is null, take ts1 as the non-null * one. Otherwise, take ts1 as the lesser endpoint. */ if (ts1IsNull) { if (te1IsNull) PG_RETURN_NULL(); /* swap null for non-null */ ts1 = te1; te1IsNull = true; } else if (!te1IsNull) { if (TIMESTAMP_GT(ts1, te1)) { Datum tt = ts1; ts1 = te1; te1 = tt; } } /* Likewise for interval 2. */ if (ts2IsNull) { if (te2IsNull) PG_RETURN_NULL(); /* swap null for non-null */ ts2 = te2; te2IsNull = true; } else if (!te2IsNull) { if (TIMESTAMP_GT(ts2, te2)) { Datum tt = ts2; ts2 = te2; te2 = tt; } } /* * At this point neither ts1 nor ts2 is null, so we can consider three * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2 */ if (TIMESTAMP_GT(ts1, ts2)) { /* * This case is ts1 < te2 OR te1 < te2, which may look redundant * but in the presence of nulls it's not quite completely so. */ if (te2IsNull) PG_RETURN_NULL(); if (TIMESTAMP_LT(ts1, te2)) PG_RETURN_BOOL(true); if (te1IsNull) PG_RETURN_NULL(); /* * If te1 is not null then we had ts1 <= te1 above, and we just * found ts1 >= te2, hence te1 >= te2. */ PG_RETURN_BOOL(false); } else if (TIMESTAMP_LT(ts1, ts2)) { /* This case is ts2 < te1 OR te2 < te1 */ if (te1IsNull) PG_RETURN_NULL(); if (TIMESTAMP_LT(ts2, te1)) PG_RETURN_BOOL(true); if (te2IsNull) PG_RETURN_NULL(); /* * If te2 is not null then we had ts2 <= te2 above, and we just * found ts2 >= te1, hence te2 >= te1. */ PG_RETURN_BOOL(false); } else { /* * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a * rather silly way of saying "true if both are nonnull, else * null". */ if (te1IsNull || te2IsNull) PG_RETURN_NULL(); PG_RETURN_BOOL(true); }#undef TIMESTAMP_GT#undef TIMESTAMP_LT}/*---------------------------------------------------------- * "Arithmetic" operators on date/times. *---------------------------------------------------------*/Datumtimestamp_smaller(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp result; /* use timestamp_cmp_internal to be sure this agrees with comparisons */ if (timestamp_cmp_internal(dt1, dt2) < 0) result = dt1; else result = dt2; PG_RETURN_TIMESTAMP(result);}Datumtimestamp_larger(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Timestamp result; if (timestamp_cmp_internal(dt1, dt2) > 0) result = dt1; else result = dt2; PG_RETURN_TIMESTAMP(result);}Datumtimestamp_mi(PG_FUNCTION_ARGS){ Timestamp dt1 = PG_GETARG_TIMESTAMP(0); Timestamp dt2 = PG_GETARG_TIMESTAMP(1); Interval *result; result = (Interval *) palloc(sizeof(Interval)); if (TIMESTAMP_NOT_FINITE(dt1) || TIMESTAMP_NOT_FINITE(dt2)) { ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("cannot subtract infinite timestamps"))); result->time = 0; } else#ifdef HAVE_INT64_TIMESTAMP result->time = (dt1 - dt2);#else result->time = JROUND(dt1 - dt2);#endif result->month = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -