📄 formatting.c
字号:
{ sscanf(inout, "%d", &tmfc->ww); return strdigits_len(inout) + SKIP_THth(suf); } else { sscanf(inout, "%02d", &tmfc->ww); return 2 + SKIP_THth(suf); } } break; case DCH_IW: if (is_to_char) { sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, date2isoweek(tm->tm_year, tm->tm_mon, tm->tm_mday)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { if (S_FM(suf) || is_next_separator(node)) { sscanf(inout, "%d", &tmfc->iw); return strdigits_len(inout) + SKIP_THth(suf); } else { sscanf(inout, "%02d", &tmfc->iw); return 2 + SKIP_THth(suf); } } break; case DCH_Q: if (is_to_char) { if (!tm->tm_mon) return -1; sprintf(inout, "%d", (tm->tm_mon - 1) / 3 + 1); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { sscanf(inout, "%1d", &tmfc->q); return 1 + SKIP_THth(suf); } break; case DCH_CC: if (is_to_char) { i = tm->tm_year / 100 + ((is_interval) ? 0 : 1); if (i <= 99 && i >= -99) sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, i); else sprintf(inout, "%d", i); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { if (S_FM(suf) || is_next_separator(node)) { sscanf(inout, "%d", &tmfc->cc); return strdigits_len(inout) + SKIP_THth(suf); } else { sscanf(inout, "%02d", &tmfc->cc); return 2 + SKIP_THth(suf); } } break; case DCH_Y_YYY: if (is_to_char) { i = ADJUST_YEAR(tm->tm_year, is_interval) / 1000; sprintf(inout, "%d,%03d", i, ADJUST_YEAR(tm->tm_year, is_interval) - (i * 1000)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { int cc; sscanf(inout, "%d,%03d", &cc, &tmfc->year); tmfc->year += (cc * 1000); tmfc->yysz = 4; return strdigits_len(inout) + 4 + SKIP_THth(suf); } break; case DCH_YYYY: case DCH_IYYY: if (is_to_char) { if (tm->tm_year <= 9999 && tm->tm_year >= -9998) sprintf(inout, "%0*d", S_FM(suf) ? 0 : 4, arg == DCH_YYYY ? ADJUST_YEAR(tm->tm_year, is_interval) : ADJUST_YEAR(date2isoyear( tm->tm_year, tm->tm_mon, tm->tm_mday), is_interval)); else sprintf(inout, "%d", arg == DCH_YYYY ? ADJUST_YEAR(tm->tm_year, is_interval) : ADJUST_YEAR(date2isoyear( tm->tm_year, tm->tm_mon, tm->tm_mday), is_interval)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { if (S_FM(suf) || is_next_separator(node)) { sscanf(inout, "%d", &tmfc->year); tmfc->yysz = 4; return strdigits_len(inout) + SKIP_THth(suf); } else { sscanf(inout, "%04d", &tmfc->year); tmfc->yysz = 4; return 4 + SKIP_THth(suf); } } break; case DCH_YYY: case DCH_IYY: if (is_to_char) { snprintf(buff, sizeof(buff), "%03d", arg == DCH_YYY ? ADJUST_YEAR(tm->tm_year, is_interval) : ADJUST_YEAR(date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday), is_interval)); i = strlen(buff); strcpy(inout, buff + (i - 3)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { sscanf(inout, "%03d", &tmfc->year); /* * 3-digit year: '100' ... '999' = 1100 ... 1999 '000' ... * '099' = 2000 ... 2099 */ if (tmfc->year >= 100) tmfc->year += 1000; else tmfc->year += 2000; tmfc->yysz = 3; return 3 + SKIP_THth(suf); } break; case DCH_YY: case DCH_IY: if (is_to_char) { snprintf(buff, sizeof(buff), "%02d", arg == DCH_YY ? ADJUST_YEAR(tm->tm_year, is_interval) : ADJUST_YEAR(date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday), is_interval)); i = strlen(buff); strcpy(inout, buff + (i - 2)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { sscanf(inout, "%02d", &tmfc->year); /* * 2-digit year: '00' ... '69' = 2000 ... 2069 '70' ... '99' * = 1970 ... 1999 */ if (tmfc->year < 70) tmfc->year += 2000; else tmfc->year += 1900; tmfc->yysz = 2; return 2 + SKIP_THth(suf); } break; case DCH_Y: case DCH_I: if (is_to_char) { snprintf(buff, sizeof(buff), "%1d", arg == DCH_Y ? ADJUST_YEAR(tm->tm_year, is_interval) : ADJUST_YEAR(date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday), is_interval)); i = strlen(buff); strcpy(inout, buff + (i - 1)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { sscanf(inout, "%1d", &tmfc->year); /* * 1-digit year: always +2000 */ tmfc->year += 2000; tmfc->yysz = 1; return 1 + SKIP_THth(suf); } break; case DCH_RM: if (is_to_char) { if (!tm->tm_mon) return -1; sprintf(inout, "%*s", S_FM(suf) ? 0 : -4, rm_months_upper[12 - tm->tm_mon]); return strlen(p_inout); } else { tmfc->mm = 12 - seq_search(inout, rm_months_upper, ALL_UPPER, FULL_SIZ, &len); CHECK_SEQ_SEARCH(len, "RM"); if (S_FM(suf)) return len; else return 4; } break; case DCH_rm: if (is_to_char) { if (!tm->tm_mon) return -1; sprintf(inout, "%*s", S_FM(suf) ? 0 : -4, rm_months_lower[12 - tm->tm_mon]); return strlen(p_inout); } else { tmfc->mm = 12 - seq_search(inout, rm_months_lower, ALL_LOWER, FULL_SIZ, &len); CHECK_SEQ_SEARCH(len, "rm"); if (S_FM(suf)) return len; else return 4; } break; case DCH_W: if (is_to_char) { sprintf(inout, "%d", (tm->tm_mday - 1) / 7 + 1); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { sscanf(inout, "%1d", &tmfc->w); return 1 + SKIP_THth(suf); } break; case DCH_J: if (is_to_char) { sprintf(inout, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)); if (S_THth(suf)) str_numth(p_inout, inout, S_TH_TYPE(suf)); return strlen(p_inout); } else { sscanf(inout, "%d", &tmfc->j); return strdigits_len(inout) + SKIP_THth(suf); } break; } return -1;}static DCHCacheEntry *DCH_cache_getnew(char *str){ DCHCacheEntry *ent = NULL; /* counter overload check - paranoia? */ if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32) { DCHCounter = 0; for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) ent->age = (++DCHCounter); } /* * Cache is full - needs remove any older entry */ if (n_DCHCache > DCH_CACHE_FIELDS) { DCHCacheEntry *old = DCHCache + 0;#ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "cache is full (%d)", n_DCHCache);#endif for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) { if (ent->age < old->age) old = ent; }#ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "OLD: '%s' AGE: %d", old->str, old->age);#endif StrNCpy(old->str, str, DCH_CACHE_SIZE + 1); /* old->format fill parser */ old->age = (++DCHCounter); return old; } else {#ifdef DEBUG_TO_FROM_CHAR elog(DEBUG_elog_output, "NEW (%d)", n_DCHCache);#endif ent = DCHCache + n_DCHCache; StrNCpy(ent->str, str, DCH_CACHE_SIZE + 1); /* ent->format fill parser */ ent->age = (++DCHCounter); ++n_DCHCache; return ent; } return NULL; /* never */}static DCHCacheEntry *DCH_cache_search(char *str){ int i = 0; DCHCacheEntry *ent; /* counter overload check - paranoia? */ if (DCHCounter + DCH_CACHE_FIELDS >= MAX_INT32) { DCHCounter = 0; for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) ent->age = (++DCHCounter); } for (ent = DCHCache; ent <= (DCHCache + DCH_CACHE_FIELDS); ent++) { if (i == n_DCHCache) break; if (strcmp(ent->str, str) == 0) { ent->age = (++DCHCounter); return ent; } i++; } return NULL;}static text *datetime_to_char_body(TmToChar *tmtc, text *fmt, bool is_interval){ FormatNode *format; char *fmt_str, *result; bool incache; int fmt_len = VARSIZE(fmt) - VARHDRSZ; int reslen; text *res; /* * Convert fmt to C string */ fmt_str = (char *) palloc(fmt_len + 1); memcpy(fmt_str, VARDATA(fmt), fmt_len); *(fmt_str + fmt_len) = '\0'; /* * Allocate workspace for result as C string */ result = palloc((fmt_len * DCH_MAX_ITEM_SIZ) + 1); *result = '\0'; /* * Allocate new memory if format picture is bigger than static cache and * not use cache (call parser always) */ if (fmt_len > DCH_CACHE_SIZE) { format = (FormatNode *) palloc((fmt_len + 1) * sizeof(FormatNode)); incache = FALSE; parse_format(format, fmt_str, DCH_keywords, DCH_suff, DCH_index, DCH_TYPE, NULL); (format + fmt_len)->type = NODE_TYPE_END; /* Paranoia? */ } else { /* * Use cache buffers */ DCHCacheEntry *ent; incache = TRUE; if ((ent = DCH_cache_search(fmt_str)) == NULL) { ent = DCH_cache_getnew(fmt_str); /* * Not in the cache, must run parser and save a new format-picture * to the cache. */ parse_format(ent->format, fmt_str, DCH_keywords, DCH_suff, DCH_index, DCH_TYPE, NULL); (ent->format + fmt_len)->type = NODE_TYPE_END; /* Paranoia? */#ifdef DEBUG_TO_FROM_CHAR /* dump_node(ent->format, fmt_len); */ /* dump_index(DCH_keywords, DCH_index); */#endif } format = ent->format; } /* The real work is here */ DCH_processor(format, result, true, is_interval, (void *) tmtc); if (!incache) pfree(format); pfree(fmt_str); /* convert C-string result to TEXT format */ reslen = strlen(result); res = (text *) palloc(reslen + VARHDRSZ); memcpy(VARDATA(res), result, reslen); VARATT_SIZEP(res) = reslen + VARHDRSZ; pfree(result); return res;}/**************************************************************************** * Public routines ***************************************************************************//* ------------------- * TIMESTAMP to_char() * ------------------- */Datumtimestamp_to_char(PG_FUNCTION_ARGS){ Timestamp dt = PG_GETARG_TIMESTAMP(0); text *fmt = PG_GETARG_TEXT_P(1), *res; TmToChar tmtc; struct pg_tm *tm; int thisdate; if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt)) PG_RETURN_NULL(); ZERO_tmtc(&tmtc); tm = tmtcTm(&tmtc); if (timestamp2tm(dt, NULL, tm, &tmtcFsec(&tmtc), NULL, NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday); tm->tm_wday = (thisdate + 1) % 7; tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1; if (!(res = datetime_to_char_body(&tmtc, fmt, false))) PG_RETURN_NULL(); PG_RETURN_TEXT_P(res);}Datumtimestamptz_to_char(PG_FUNCTION_ARGS){ TimestampTz dt = PG_GETARG_TIMESTAMP(0); text *fmt = PG_GETARG_TEXT_P(1), *res; TmToChar tmtc; int tz; struct pg_tm *tm; int thisdate; if ((VARSIZE(fmt) - VARHDRSZ) <= 0 || TIMESTAMP_NOT_FINITE(dt)) PG_RETURN_NULL(); ZERO_tmtc(&tmtc); tm = tmtcTm(&tmtc); if (timestamp2tm(dt, &tz, tm, &tmtcFsec(&tmtc), &tmtcTzn(&tmtc), NULL) != 0) ereport(ERROR, (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), errmsg("timestamp out of range"))); thisdate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday); tm->tm_wday = (thisdate + 1) % 7; tm->tm_yday = thisdate - date2j(tm->tm_year, 1, 1) + 1; if (!(res = datetime_to_char_body(&tmtc, fmt, false))) PG_RETURN_NULL(); PG_RETURN_TEXT_P(res);}/* ------------------- * INTERVAL to_char() * ------------------- */Datuminterval_to_char(PG_FUNCTION_ARGS){ Interval *it = PG_GETARG_INTERVAL_P(0); text *fmt = PG_GETARG_TEXT_P(1), *res; TmToChar tmtc; struct pg_tm *tm; if ((VARSIZE(fmt) - VARHDRSZ) <= 0) PG_RETURN_NULL(); ZERO_tmtc(&tmtc); tm = tmtcTm(&tmtc); if (interval2tm(*it, tm, &tmtcFsec(&tmtc)) != 0) PG_RETURN_NULL(); /* wday is meaningless, yday approximates the total span in days */ tm->tm_yday = (tm->tm_year * MONTHS_PER_YEAR + tm->tm_mon) * DAYS_PER_MONTH + tm->tm_mday; if (!(res = datetime_to_char_body(&tmtc, fmt, true))) PG_RETURN_NULL(); PG_RETURN_TEXT_P(res);}/* --------------------- * TO_TIMESTAMP() * * Make Timestamp from date_str which is formatted at argument 'fmt' * ( to_timestamp is reverse to_char() ) * --------------------- */Datum
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -