datetime.c
来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 717 行 · 第 1/2 页
C
717 行
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/datetime.c,v 1.34 2007/11/15 21:14:45 momjian Exp $ */#include "postgres_fe.h"#include <time.h>#include <ctype.h>#include <float.h>#include <limits.h>#include "extern.h"#include "dt.h"#include "pgtypes_error.h"#include "pgtypes_date.h"date *PGTYPESdate_new(void){ date *result; result = (date *) pgtypes_alloc(sizeof(date)); /* result can be NULL if we run out of memory */ return result;}voidPGTYPESdate_free(date * d){ free(d);}datePGTYPESdate_from_timestamp(timestamp dt){ date dDate; dDate = 0; /* suppress compiler warning */ if (!TIMESTAMP_NOT_FINITE(dt)) {#ifdef HAVE_INT64_TIMESTAMP /* Microseconds to days */ dDate = (dt / USECS_PER_DAY);#else /* Seconds to days */ dDate = (dt / (double) SECS_PER_DAY);#endif } return dDate;}datePGTYPESdate_from_asc(char *str, char **endptr){ date dDate; fsec_t fsec; struct tm tt, *tm = &tt; int dtype; int nf; char *field[MAXDATEFIELDS]; int ftype[MAXDATEFIELDS]; char lowstr[MAXDATELEN + 1]; char *realptr; char **ptr = (endptr != NULL) ? endptr : &realptr; bool EuroDates = FALSE; errno = 0; if (strlen(str) >= sizeof(lowstr)) { errno = PGTYPES_DATE_BAD_DATE; return INT_MIN; } if (ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0 || DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, EuroDates) != 0) { errno = PGTYPES_DATE_BAD_DATE; return INT_MIN; } switch (dtype) { case DTK_DATE: break; case DTK_EPOCH: GetEpochTime(tm); break; default: errno = PGTYPES_DATE_BAD_DATE; return INT_MIN; } dDate = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1)); return dDate;}char *PGTYPESdate_to_asc(date dDate){ struct tm tt, *tm = &tt; char buf[MAXDATELEN + 1]; int DateStyle = 1; bool EuroDates = FALSE; j2date(dDate + date2j(2000, 1, 1), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); EncodeDateOnly(tm, DateStyle, buf, EuroDates); return pgtypes_strdup(buf);}voidPGTYPESdate_julmdy(date jd, int *mdy){ int y, m, d; j2date((int) (jd + date2j(2000, 1, 1)), &y, &m, &d); mdy[0] = m; mdy[1] = d; mdy[2] = y;}voidPGTYPESdate_mdyjul(int *mdy, date * jdate){ /* month is mdy[0] */ /* day is mdy[1] */ /* year is mdy[2] */ *jdate = (date) (date2j(mdy[2], mdy[0], mdy[1]) - date2j(2000, 1, 1));}intPGTYPESdate_dayofweek(date dDate){ /* * Sunday: 0 Monday: 1 Tuesday: 2 Wednesday: 3 Thursday: 4 * Friday: 5 Saturday: 6 */ return (int) (dDate + date2j(2000, 1, 1) + 1) % 7;}voidPGTYPESdate_today(date * d){ struct tm ts; GetCurrentDateTime(&ts); *d = date2j(ts.tm_year, ts.tm_mon, ts.tm_mday) - date2j(2000, 1, 1); return;}#define PGTYPES_DATE_NUM_MAX_DIGITS 20 /* should suffice for most * years... */#define PGTYPES_FMTDATE_DAY_DIGITS_LZ 1 /* LZ means "leading zeroes" */#define PGTYPES_FMTDATE_DOW_LITERAL_SHORT 2#define PGTYPES_FMTDATE_MONTH_DIGITS_LZ 3#define PGTYPES_FMTDATE_MONTH_LITERAL_SHORT 4#define PGTYPES_FMTDATE_YEAR_DIGITS_SHORT 5#define PGTYPES_FMTDATE_YEAR_DIGITS_LONG 6intPGTYPESdate_fmt_asc(date dDate, char *fmtstring, char *outbuf){ static struct { char *format; int component; } mapping[] = { /* * format items have to be sorted according to their length, since the * first pattern that matches gets replaced by its value */ { "ddd", PGTYPES_FMTDATE_DOW_LITERAL_SHORT }, { "dd", PGTYPES_FMTDATE_DAY_DIGITS_LZ }, { "mmm", PGTYPES_FMTDATE_MONTH_LITERAL_SHORT }, { "mm", PGTYPES_FMTDATE_MONTH_DIGITS_LZ }, { "yyyy", PGTYPES_FMTDATE_YEAR_DIGITS_LONG }, { "yy", PGTYPES_FMTDATE_YEAR_DIGITS_SHORT }, { NULL, 0 } }; union un_fmt_comb replace_val; int replace_type; int i; int dow; char *start_pattern; struct tm tm; /* copy the string over */ strcpy(outbuf, fmtstring); /* get the date */ j2date(dDate + date2j(2000, 1, 1), &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday)); dow = PGTYPESdate_dayofweek(dDate); for (i = 0; mapping[i].format != NULL; i++) { while ((start_pattern = strstr(outbuf, mapping[i].format)) != NULL) { switch (mapping[i].component) { case PGTYPES_FMTDATE_DOW_LITERAL_SHORT: replace_val.str_val = pgtypes_date_weekdays_short[dow]; replace_type = PGTYPES_TYPE_STRING_CONSTANT; break; case PGTYPES_FMTDATE_DAY_DIGITS_LZ: replace_val.uint_val = tm.tm_mday; replace_type = PGTYPES_TYPE_UINT_2_LZ; break; case PGTYPES_FMTDATE_MONTH_LITERAL_SHORT: replace_val.str_val = months[tm.tm_mon - 1]; replace_type = PGTYPES_TYPE_STRING_CONSTANT; break; case PGTYPES_FMTDATE_MONTH_DIGITS_LZ: replace_val.uint_val = tm.tm_mon; replace_type = PGTYPES_TYPE_UINT_2_LZ; break; case PGTYPES_FMTDATE_YEAR_DIGITS_LONG: replace_val.uint_val = tm.tm_year; replace_type = PGTYPES_TYPE_UINT_4_LZ; break; case PGTYPES_FMTDATE_YEAR_DIGITS_SHORT: replace_val.uint_val = tm.tm_year % 100; replace_type = PGTYPES_TYPE_UINT_2_LZ; break; default: /* * should not happen, set something anyway */ replace_val.str_val = " "; replace_type = PGTYPES_TYPE_STRING_CONSTANT; } switch (replace_type) { case PGTYPES_TYPE_STRING_MALLOCED: case PGTYPES_TYPE_STRING_CONSTANT: strncpy(start_pattern, replace_val.str_val, strlen(replace_val.str_val)); if (replace_type == PGTYPES_TYPE_STRING_MALLOCED) free(replace_val.str_val); break; case PGTYPES_TYPE_UINT: { char *t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS); if (!t) return -1; snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS, "%u", replace_val.uint_val); strncpy(start_pattern, t, strlen(t)); free(t); } break; case PGTYPES_TYPE_UINT_2_LZ: { char *t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS); if (!t) return -1; snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS, "%02u", replace_val.uint_val); strncpy(start_pattern, t, strlen(t)); free(t); } break; case PGTYPES_TYPE_UINT_4_LZ: { char *t = pgtypes_alloc(PGTYPES_DATE_NUM_MAX_DIGITS); if (!t) return -1; snprintf(t, PGTYPES_DATE_NUM_MAX_DIGITS, "%04u", replace_val.uint_val); strncpy(start_pattern, t, strlen(t)); free(t); } break; default: /* * doesn't happen (we set replace_type to * PGTYPES_TYPE_STRING_CONSTANT in case of an error above) */ break; } } } return 0;}/* * PGTYPESdate_defmt_asc * * function works as follows: * - first we analyze the paramters * - if this is a special case with no delimiters, add delimters * - find the tokens. First we look for numerical values. If we have found * less than 3 tokens, we check for the months' names and thereafter for * the abbreviations of the months' names. * - then we see which parameter should be the date, the month and the * year and from these values we calculate the date */#define PGTYPES_DATE_MONTH_MAXLENGTH 20 /* probably even less :-) */intPGTYPESdate_defmt_asc(date * d, char *fmt, char *str){ /* * token[2] = { 4,6 } means that token 2 starts at position 4 and ends at * (including) position 6 */ int token[3][2]; int token_values[3] = {-1, -1, -1}; char *fmt_token_order; char *fmt_ystart, *fmt_mstart, *fmt_dstart; int i; int reading_digit; int token_count; char *str_copy; struct tm tm; tm.tm_year = tm.tm_mon = tm.tm_mday = 0; /* keep compiler quiet */ if (!d || !str || !fmt) { errno = PGTYPES_DATE_ERR_EARGS; return -1; } /* analyze the fmt string */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?