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 + -
显示快捷键?