dt_common.c
来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,528 行 · 第 1/5 页
C
2,528 行
char *pgtypes_date_weekdays_short[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL};char *pgtypes_date_months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL};static datetkn *datebsearch(char *key, datetkn *base, unsigned int nel){ datetkn *last = base + nel - 1, *position; int result; while (last >= base) { position = base + ((last - base) >> 1); result = key[0] - position->token[0]; if (result == 0) { result = strncmp(key, position->token, TOKMAXLEN); if (result == 0) return position; } if (result < 0) last = position - 1; else base = position + 1; } return NULL;}/* DecodeUnits() * Decode text string using lookup table. * This routine supports time interval decoding. */intDecodeUnits(int field, char *lowtoken, int *val){ int type; datetkn *tp; if ((deltacache[field] != NULL) && (strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0)) tp = deltacache[field]; else tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl); deltacache[field] = tp; if (tp == NULL) { type = UNKNOWN_FIELD; *val = 0; } else { type = tp->type; if ((type == TZ) || (type == DTZ)) *val = FROMVAL(tp); else *val = tp->value; } return type;} /* DecodeUnits() *//* * Calendar time to Julian date conversions. * Julian date is commonly used in astronomical applications, * since it is numerically accurate and computationally simple. * The algorithms here will accurately convert between Julian day * and calendar date for all non-negative Julian days * (i.e. from Nov 24, -4713 on). * * These routines will be used by other date/time packages * - thomas 97/02/25 * * Rewritten to eliminate overflow problems. This now allows the * routines to work correctly for all Julian day counts from * 0 to 2147483647 (Nov 24, -4713 to Jun 3, 5874898) assuming * a 32-bit integer. Longer types should also work to the limits * of their precision. */intdate2j(int y, int m, int d){ int julian; int century; if (m > 2) { m += 1; y += 4800; } else { m += 13; y += 4799; } century = y / 100; julian = y * 365 - 32167; julian += y / 4 - century + century / 4; julian += 7834 * m / 256 + d; return julian;} /* date2j() */voidj2date(int jd, int *year, int *month, int *day){ unsigned int julian; unsigned int quad; unsigned int extra; int y; julian = jd; julian += 32044; quad = julian / 146097; extra = (julian - quad * 146097) * 4 + 3; julian += 60 + quad * 3 + extra / 146097; quad = julian / 1461; julian -= quad * 1461; y = julian * 4 / 1461; julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366)) + 123; y += quad * 4; *year = y - 4800; quad = julian * 2141 / 65536; *day = julian - 7834 * quad / 256; *month = (quad + 10) % 12 + 1; return;} /* j2date() *//* DecodeSpecial() * Decode text string using lookup table. * Implement a cache lookup since it is likely that dates * will be related in format. */static intDecodeSpecial(int field, char *lowtoken, int *val){ int type; datetkn *tp; if ((datecache[field] != NULL) && (strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0)) tp = datecache[field]; else { tp = NULL; if (!tp) tp = datebsearch(lowtoken, datetktbl, szdatetktbl); } datecache[field] = tp; if (tp == NULL) { type = UNKNOWN_FIELD; *val = 0; } else { type = tp->type; switch (type) { case TZ: case DTZ: case DTZMOD: *val = FROMVAL(tp); break; default: *val = tp->value; break; } } return type;} /* DecodeSpecial() *//* EncodeDateOnly() * Encode date as local time. */intEncodeDateOnly(struct tm * tm, int style, char *str, bool EuroDates){ if ((tm->tm_mon < 1) || (tm->tm_mon > 12)) return -1; switch (style) { case USE_ISO_DATES: /* compatible with ISO date formats */ if (tm->tm_year > 0) sprintf(str, "%04d-%02d-%02d", tm->tm_year, tm->tm_mon, tm->tm_mday); else sprintf(str, "%04d-%02d-%02d %s", -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC"); break; case USE_SQL_DATES: /* compatible with Oracle/Ingres date formats */ if (EuroDates) sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon); else sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday); if (tm->tm_year > 0) sprintf((str + 5), "/%04d", tm->tm_year); else sprintf((str + 5), "/%04d %s", -(tm->tm_year - 1), "BC"); break; case USE_GERMAN_DATES: /* German-style date format */ sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon); if (tm->tm_year > 0) sprintf((str + 5), ".%04d", tm->tm_year); else sprintf((str + 5), ".%04d %s", -(tm->tm_year - 1), "BC"); break; case USE_POSTGRES_DATES: default: /* traditional date-only style for Postgres */ if (EuroDates) sprintf(str, "%02d-%02d", tm->tm_mday, tm->tm_mon); else sprintf(str, "%02d-%02d", tm->tm_mon, tm->tm_mday); if (tm->tm_year > 0) sprintf((str + 5), "-%04d", tm->tm_year); else sprintf((str + 5), "-%04d %s", -(tm->tm_year - 1), "BC"); break; } return TRUE;} /* EncodeDateOnly() */static voidTrimTrailingZeros(char *str){ int len = strlen(str); /* chop off trailing zeros... but leave at least 2 fractional digits */ while ((*(str + len - 1) == '0') && (*(str + len - 3) != '.')) { len--; *(str + len) = '\0'; }}/* EncodeDateTime() * Encode date and time interpreted as local time. * Support several date styles: * Postgres - day mon hh:mm:ss yyyy tz * SQL - mm/dd/yyyy hh:mm:ss.ss tz * ISO - yyyy-mm-dd hh:mm:ss+/-tz * German - dd.mm.yyyy hh:mm:ss tz * Variants (affects order of month and day for Postgres and SQL styles): * US - mm/dd/yyyy * European - dd/mm/yyyy */intEncodeDateTime(struct tm * tm, fsec_t fsec, int *tzp, char **tzn, int style, char *str, bool EuroDates){ int day, hour, min; switch (style) { case USE_ISO_DATES: /* Compatible with ISO-8601 date formats */ sprintf(str, "%04d-%02d-%02d %02d:%02d", ((tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1)), tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min); /* * Print fractional seconds if any. The field widths here * should be at least equal to MAX_TIMESTAMP_PRECISION. * * In float mode, don't print fractional seconds before 1 AD, * since it's unlikely there's any precision left ... */#ifdef HAVE_INT64_TIMESTAMP if (fsec != 0) { sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);#else if ((fsec != 0) && (tm->tm_year > 0)) { sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);#endif TrimTrailingZeros(str); } else sprintf((str + strlen(str)), ":%02d", tm->tm_sec); if (tm->tm_year <= 0) sprintf((str + strlen(str)), " BC"); /* * tzp == NULL indicates that we don't want *any* time zone * info in the output string. *tzn != NULL indicates that we * have alpha time zone info available. tm_isdst != -1 * indicates that we have a valid time zone translation. */ if ((tzp != NULL) && (tm->tm_isdst >= 0)) { hour = -(*tzp / 3600); min = ((abs(*tzp) / 60) % 60); sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); } break; case USE_SQL_DATES: /* Compatible with Oracle/Ingres date formats */ if (EuroDates) sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon); else sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday); sprintf((str + 5), "/%04d %02d:%02d", ((tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1)), tm->tm_hour, tm->tm_min); /* * Print fractional seconds if any. The field widths here * should be at least equal to MAX_TIMESTAMP_PRECISION. * * In float mode, don't print fractional seconds before 1 AD, * since it's unlikely there's any precision left ... */#ifdef HAVE_INT64_TIMESTAMP if (fsec != 0) { sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);#else if ((fsec != 0) && (tm->tm_year > 0)) { sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);#endif TrimTrailingZeros(str); } else sprintf((str + strlen(str)), ":%02d", tm->tm_sec); if (tm->tm_year <= 0) sprintf((str + strlen(str)), " BC"); if ((tzp != NULL) && (tm->tm_isdst >= 0)) { if (*tzn != NULL) sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); else { hour = -(*tzp / 3600); min = ((abs(*tzp) / 60) % 60); sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); } } break; case USE_GERMAN_DATES: /* German variant on European style */ sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon); sprintf((str + 5), ".%04d %02d:%02d", ((tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1)), tm->tm_hour, tm->tm_min); /* * Print fractional seconds if any. The field widths here * should be at least equal to MAX_TIMESTAMP_PRECISION. * * In float mode, don't print fractional seconds before 1 AD, * since it's unlikely there's any precision left ... */#ifdef HAVE_INT64_TIMESTAMP if (fsec != 0) { sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);#else if ((fsec != 0) && (tm->tm_year > 0)) { sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);#endif TrimTrailingZeros(str); } else sprintf((str + strlen(str)), ":%02d", tm->tm_sec); if (tm->tm_year <= 0) sprintf((str + strlen(str)), " BC"); if ((tzp != NULL) && (tm->tm_isdst >= 0)) { if (*tzn != NULL) sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); else { hour = -(*tzp / 3600); min = ((abs(*tzp) / 60) % 60); sprintf((str + strlen(str)), ((min != 0) ? "%+03d:%02d" : "%+03d"), hour, min); } } break; case USE_POSTGRES_DATES: default: /* Backward-compatible with traditional Postgres abstime dates */ day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday); tm->tm_wday = (int) ((day + date2j(2000, 1, 1) + 1) % 7); strncpy(str, days[tm->tm_wday], 3); strcpy((str + 3), " "); if (EuroDates) sprintf((str + 4), "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]); else sprintf((str + 4), "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday); sprintf((str + 10), " %02d:%02d", tm->tm_hour, tm->tm_min); /* * Print fractional seconds if any. The field widths here * should be at least equal to MAX_TIMESTAMP_PRECISION. * * In float mode, don't print fractional seconds before 1 AD, * since it's unlikely there's any precision left ... */#ifdef HAVE_INT64_TIMESTAMP if (fsec != 0) { sprintf((str + strlen(str)), ":%02d.%06d", tm->tm_sec, fsec);#else if ((fsec != 0) && (tm->tm_year > 0)) { sprintf((str + strlen(str)), ":%09.6f", tm->tm_sec + fsec);#endif TrimTrailingZeros(str); } else sprintf((str + strlen(str)), ":%02d", tm->tm_sec); sprintf((str + strlen(str)), " %04d", ((tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1))); if (tm->tm_year <= 0) sprintf((str + strlen(str)), " BC"); if ((tzp != NULL) && (tm->tm_isdst >= 0)) { if (*tzn != NULL) sprintf((str + strlen(str)), " %.*s", MAXTZLEN, *tzn); else { /* * We have a time zone, but no string version. Use the * numeric form, but be sure to include a leading * space to avoid formatting something which would be * rejected by the date/time parser later. - thomas * 2001-10-19 */ hour = -(*tzp / 3600); min = ((abs(*tzp) / 60) % 60); sprintf((str + strlen(str)), ((min != 0) ? " %+03d:%02d" : " %+03d"), hour, min); } } break; } return TRUE;} /* EncodeDateTime() */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() */static voidabstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn){ time_t time = (time_t) _time; struct tm *tx;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?