📄 date.c
字号:
Datumtimetz_gt(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);}Datumtimetz_ge(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);}Datumtimetz_cmp(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); PG_RETURN_INT32(timetz_cmp_internal(time1, time2));}/* * timetz, being an unusual size, needs a specialized hash function. */Datumtimetz_hash(PG_FUNCTION_ARGS){ TimeTzADT *key = PG_GETARG_TIMETZADT_P(0); /* * Specify hash length as sizeof(double) + sizeof(int4), not as * sizeof(TimeTzADT), 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->zone));}Datumtimetz_larger(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; if (timetz_cmp_internal(time1, time2) > 0) result = time1; else result = time2; PG_RETURN_TIMETZADT_P(result);}Datumtimetz_smaller(PG_FUNCTION_ARGS){ TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0); TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; if (timetz_cmp_internal(time1, time2) < 0) result = time1; else result = time2; PG_RETURN_TIMETZADT_P(result);}/* timetz_pl_interval() * Add interval to timetz. */Datumtimetz_pl_interval(PG_FUNCTION_ARGS){ TimeTzADT *time = PG_GETARG_TIMETZADT_P(0); Interval *span = PG_GETARG_INTERVAL_P(1); TimeTzADT *result;#ifndef HAVE_INT64_TIMESTAMP TimeTzADT time1;#endif result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = time->time + span->time; result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY; if (result->time < INT64CONST(0)) result->time += USECS_PER_DAY;#else result->time = time->time + span->time; TMODULO(result->time, time1.time, (double) SECS_PER_DAY); if (result->time < 0) result->time += SECS_PER_DAY;#endif result->zone = time->zone; PG_RETURN_TIMETZADT_P(result);}/* timetz_mi_interval() * Subtract interval from timetz. */Datumtimetz_mi_interval(PG_FUNCTION_ARGS){ TimeTzADT *time = PG_GETARG_TIMETZADT_P(0); Interval *span = PG_GETARG_INTERVAL_P(1); TimeTzADT *result;#ifndef HAVE_INT64_TIMESTAMP TimeTzADT time1;#endif result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = time->time - span->time; result->time -= result->time / USECS_PER_DAY * USECS_PER_DAY; if (result->time < INT64CONST(0)) result->time += USECS_PER_DAY;#else result->time = time->time - span->time; TMODULO(result->time, time1.time, (double) SECS_PER_DAY); if (result->time < 0) result->time += SECS_PER_DAY;#endif result->zone = time->zone; PG_RETURN_TIMETZADT_P(result);}/* overlaps_timetz() --- 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_timetz(PG_FUNCTION_ARGS){ /* * The arguments are TimeTzADT *, but we leave them as generic Datums for * convenience of notation --- and to avoid dereferencing nulls. */ 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 TIMETZ_GT(t1,t2) \ DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))#define TIMETZ_LT(t1,t2) \ DatumGetBool(DirectFunctionCall2(timetz_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 (TIMETZ_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 (TIMETZ_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 (TIMETZ_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 (TIMETZ_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 (TIMETZ_LT(ts1, ts2)) { /* This case is ts2 < te1 OR te2 < te1 */ if (te1IsNull) PG_RETURN_NULL(); if (TIMETZ_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 TIMETZ_GT#undef TIMETZ_LT}Datumtimetz_time(PG_FUNCTION_ARGS){ TimeTzADT *timetz = PG_GETARG_TIMETZADT_P(0); TimeADT result; /* swallow the time zone and just return the time */ result = timetz->time; PG_RETURN_TIMEADT(result);}Datumtime_timetz(PG_FUNCTION_ARGS){ TimeADT time = PG_GETARG_TIMEADT(0); TimeTzADT *result; struct pg_tm tt, *tm = &tt; fsec_t fsec; int tz; GetCurrentDateTime(tm); time2tm(time, tm, &fsec); tz = DetermineTimeZoneOffset(tm, global_timezone); result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); result->time = time; result->zone = tz; PG_RETURN_TIMETZADT_P(result);}/* timestamptz_timetz() * Convert timestamp to timetz data type. */Datumtimestamptz_timetz(PG_FUNCTION_ARGS){ TimestampTz timestamp = PG_GETARG_TIMESTAMP(0); TimeTzADT *result; struct pg_tm tt, *tm = &tt; int tz; fsec_t fsec; char *tzn; if (TIMESTAMP_NOT_FINITE(timestamp)) PG_RETURN_NULL(); if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); tm2timetz(tm, fsec, tz, result); PG_RETURN_TIMETZADT_P(result);}/* datetimetz_timestamptz() * Convert date and timetz to timestamp with time zone data type. * Timestamp is stored in GMT, so add the time zone * stored with the timetz to the result. * - thomas 2000-03-10 */Datumdatetimetz_timestamptz(PG_FUNCTION_ARGS){ DateADT date = PG_GETARG_DATEADT(0); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); TimestampTz result;#ifdef HAVE_INT64_TIMESTAMP result = date * USECS_PER_DAY + time->time + time->zone * USECS_PER_SEC;#else result = date * (double) SECS_PER_DAY + time->time + time->zone;#endif PG_RETURN_TIMESTAMP(result);}/* timetz_text() * Convert timetz to text data type. */Datumtimetz_text(PG_FUNCTION_ARGS){ /* Input is a Timetz, but may as well leave it in Datum form */ Datum timetz = PG_GETARG_DATUM(0); text *result; char *str; int len; str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz)); len = strlen(str) + VARHDRSZ; result = palloc(len); VARATT_SIZEP(result) = len; memmove(VARDATA(result), str, (len - VARHDRSZ)); pfree(str); PG_RETURN_TEXT_P(result);}/* text_timetz() * Convert text string to timetz. * Text type is not null terminated, so use temporary string * then call the standard input routine. */Datumtext_timetz(PG_FUNCTION_ARGS){ text *str = PG_GETARG_TEXT_P(0); int i; char *sp, *dp, dstr[MAXDATELEN + 1]; if (VARSIZE(str) - VARHDRSZ > MAXDATELEN) ereport(ERROR, (errcode(ERRCODE_INVALID_DATETIME_FORMAT), errmsg("invalid input syntax for type time with time zone: \"%s\"", VARDATA(str)))); sp = VARDATA(str); dp = dstr; for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++) *dp++ = *sp++; *dp = '\0'; return DirectFunctionCall3(timetz_in, CStringGetDatum(dstr), ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1));}/* timetz_part() * Extract specified field from time type. */Datumtimetz_part(PG_FUNCTION_ARGS){ text *units = PG_GETARG_TEXT_P(0); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); float8 result; int type, val; char *lowunits; lowunits = downcase_truncate_identifier(VARDATA(units), VARSIZE(units) - VARHDRSZ, false); type = DecodeUnits(0, lowunits, &val); if (type == UNKNOWN_FIELD) type = DecodeSpecial(0, lowunits, &val); if (type == UNITS) { double dummy; int tz; fsec_t fsec; struct pg_tm tt, *tm = &tt; timetz2tm(time, tm, &fsec, &tz); switch (val) { case DTK_TZ: result = -tz; break; case DTK_TZ_MINUTE: result = -tz; result /= SECS_PER_MINUTE; FMODULO(result, dummy, (double) SECS_PER_MINUTE); break; case DTK_TZ_HOUR: dummy = -tz; FMODULO(dummy, result, (double) SECS_PER_HOUR); break; case DTK_MICROSEC:#ifdef HAVE_INT64_TIMESTAMP result = tm->tm_sec * USECS_PER_SEC + fsec;#else result = (tm->tm_sec + fsec) * 1000000;#endif break; case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP result = tm->tm_sec * INT64CONST(1000) + fsec / INT64CONST(1000);#else result = (tm->tm_sec + fsec) * 1000;#endif break; case DTK_SECOND:#ifdef HAVE_INT64_TIMESTAMP result = tm->tm_sec + fsec / USECS_PER_SEC;#else result = tm->tm_sec + fsec;#endif break; case DTK_MINUTE: result = tm->tm_min; break; case DTK_HOUR: result = tm->tm_hour; break; case DTK_DAY: case DTK_MONTH: case DTK_QUARTER: case DTK_YEAR: case DTK_DECADE: case DTK_CENTURY: case DTK_MILLENNIUM: default: ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"time with time zone\" units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); result = 0; } } else if (type == RESERV && val == DTK_EPOCH) {#ifdef HAVE_INT64_TIMESTAMP result = time->time / 1000000.0 + time->zone;#else result = time->time + time->zone;#endif } else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"time with time zone\" units \"%s\" not recognized", DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(units)))))); result = 0; } PG_RETURN_FLOAT8(result);}/* timetz_zone() * Encode time with time zone type with specified time zone. * Applies DST rules as of the current date. */Datumtimetz_zone(PG_FUNCTION_ARGS){ text *zone = PG_GETARG_TEXT_P(0); TimeTzADT *t = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; int tz; char tzname[TZ_STRLEN_MAX + 1]; int len; pg_tz *tzp; /* * Look up the requested timezone. First we look in the timezone database * (to handle cases like "America/New_York"), and if that fails, we look * in the date token table (to handle cases like "EST"). */ len = Min(VARSIZE(zone) - VARHDRSZ, TZ_STRLEN_MAX); memcpy(tzname, VARDATA(zone), len); tzname[len] = '\0'; tzp = pg_tzset(tzname); if (tzp) { /* Get the offset-from-GMT that is valid today for the selected zone */ pg_time_t now; struct pg_tm *tm; now = time(NULL); tm = pg_localtime(&now, tzp); tz = -tm->tm_gmtoff; } else { char *lowzone; int type, val; lowzone = downcase_truncate_identifier(VARDATA(zone), VARSIZE(zone) - VARHDRSZ, false); type = DecodeSpecial(0, lowzone, &val); if (type == TZ || type == DTZ) tz = val * 60; else { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("time zone \"%s\" not recognized", tzname))); tz = 0; /* keep compiler quiet */ } } result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = t->time + (t->zone - tz) * USECS_PER_SEC; while (result->time < INT64CONST(0)) result->time += USECS_PER_DAY; while (result->time >= USECS_PER_DAY) result->time -= USECS_PER_DAY;#else result->time = t->time + (t->zone - tz); while (result->time < 0) result->time += SECS_PER_DAY; while (result->time >= SECS_PER_DAY) result->time -= SECS_PER_DAY;#endif result->zone = tz; PG_RETURN_TIMETZADT_P(result);}/* timetz_izone() * Encode time with time zone type with specified time interval as time zone. */Datumtimetz_izone(PG_FUNCTION_ARGS){ Interval *zone = PG_GETARG_INTERVAL_P(0); TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); TimeTzADT *result; int tz; if (zone->month != 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("\"interval\" time zone \"%s\" not valid", DatumGetCString(DirectFunctionCall1(interval_out, PointerGetDatum(zone))))));#ifdef HAVE_INT64_TIMESTAMP tz = -(zone->time / USECS_PER_SEC);#else tz = -(zone->time);#endif result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP result->time = time->time + (time->zone - tz) * USECS_PER_SEC; while (result->time < INT64CONST(0)) result->time += USECS_PER_DAY; while (result->time >= USECS_PER_DAY) result->time -= USECS_PER_DAY;#else result->time = time->time + (time->zone - tz); while (result->time < 0) result->time += SECS_PER_DAY; while (result->time >= SECS_PER_DAY) result->time -= SECS_PER_DAY;#endif result->zone = tz; PG_RETURN_TIMETZADT_P(result);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -