⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 timestamp.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "postgres_fe.h"#include <time.h>#include <float.h>#include <limits.h>#include <math.h>#ifdef __FAST_MATH__#error -ffast-math is known to break this code#endif#include "extern.h"#include "dt.h"#include "pgtypes_timestamp.h"#include "pgtypes_date.h"int PGTYPEStimestamp_defmt_scan(char **, char *, timestamp *, int *, int *, int *,							int *, int *, int *, int *);#ifdef HAVE_INT64_TIMESTAMPstatic int64time2t(const int hour, const int min, const int sec, const fsec_t fsec){	return (((((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec) * USECS_PER_SEC) + fsec;}	/* time2t() */#elsestatic doubletime2t(const int hour, const int min, const int sec, const fsec_t fsec){	return (((hour * MINS_PER_HOUR) + min) * SECS_PER_MINUTE) + sec + fsec;}	/* time2t() */#endifstatic timestampdt2local(timestamp dt, int tz){#ifdef HAVE_INT64_TIMESTAMP	dt -= (tz * USECS_PER_SEC);#else	dt -= tz;#endif	return dt;}	/* dt2local() *//* tm2timestamp() * Convert a tm structure to a timestamp data type. * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * * Returns -1 on failure (overflow). */inttm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, timestamp * result){#ifdef HAVE_INT64_TIMESTAMP	int			dDate;	int64		time;#else	double		dDate,				time;#endif	/* Julian day routines are not correct for negative Julian days */	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))		return -1;	dDate = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1);	time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);#ifdef HAVE_INT64_TIMESTAMP	*result = (dDate * USECS_PER_DAY) + time;	/* check for major overflow */	if ((*result - time) / USECS_PER_DAY != dDate)		return -1;	/* check for just-barely overflow (okay except time-of-day wraps) */	if ((*result < 0 && dDate >= 0) ||		(*result >= 0 && dDate < 0))		return -1;#else	*result = dDate * SECS_PER_DAY + time;#endif	if (tzp != NULL)		*result = dt2local(*result, -(*tzp));	return 0;}	/* tm2timestamp() */static timestampSetEpochTimestamp(void){	timestamp	dt;	struct tm	tt,			   *tm = &tt;	GetEpochTime(tm);	tm2timestamp(tm, 0, NULL, &dt);	return dt;}	/* SetEpochTimestamp() */static voiddt2time(timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP	int64		time;#else	double		time;#endif	time = jd;#ifdef HAVE_INT64_TIMESTAMP	*hour = time / USECS_PER_HOUR;	time -= (*hour) * USECS_PER_HOUR;	*min = time / USECS_PER_MINUTE;	time -= (*min) * USECS_PER_MINUTE;	*sec = time / USECS_PER_SEC;	*fsec = time - *sec * USECS_PER_SEC;	*sec = time / USECS_PER_SEC;	*fsec = time - *sec * USECS_PER_SEC;#else	*hour = time / SECS_PER_HOUR;	time -= (*hour) * SECS_PER_HOUR;	*min = time / SECS_PER_MINUTE;	time -= (*min) * SECS_PER_MINUTE;	*sec = time;	*fsec = time - *sec;#endif}	/* dt2time() *//* timestamp2tm() * Convert timestamp data type to POSIX time structure. * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * Returns: *	 0 on success *	-1 on out of range * * For dates within the system-supported time_t range, convert to the *	local time zone. If out of this range, leave as GMT. - tgl 97/05/27 */static inttimestamp2tm(timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn){#ifdef HAVE_INT64_TIMESTAMP	int64		dDate,				date0;	int64		time;#else	double		dDate,				date0;	double		time;#endif	time_t		utime;#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)	struct tm  *tx;#endif	date0 = date2j(2000, 1, 1);#ifdef HAVE_INT64_TIMESTAMP	time = dt;	TMODULO(time, dDate, USECS_PER_DAY);	if (time < INT64CONST(0))	{		time += USECS_PER_DAY;		dDate -= 1;	}	/* add offset to go from J2000 back to standard Julian date */	dDate += date0;	/* Julian day routine does not work for negative Julian days */	if (dDate < 0 || dDate > (timestamp) INT_MAX)		return -1;	j2date((int) dDate, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);	dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);#else	time = dt;	TMODULO(time, dDate, (double) SECS_PER_DAY);	if (time < 0)	{		time += SECS_PER_DAY;		dDate -= 1;	}	/* add offset to go from J2000 back to standard Julian date */	dDate += date0;recalc_d:	/* Julian day routine does not work for negative Julian days */	if (dDate < 0 || dDate > (timestamp) INT_MAX)		return -1;	j2date((int) dDate, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);recalc_t:	dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);	*fsec = TSROUND(*fsec);	/* roundoff may need to propagate to higher-order fields */	if (*fsec >= 1.0)	{		time = ceil(time);		if (time >= (double) SECS_PER_DAY)		{			time = 0;			dDate += 1;			goto recalc_d;		}		goto recalc_t;	}#endif	if (tzp != NULL)	{		/*		 * Does this fall within the capabilities of the localtime()		 * interface? Then use this to rotate to the local time zone.		 */		if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))		{#ifdef HAVE_INT64_TIMESTAMP			utime = dt / USECS_PER_SEC +				((date0 - date2j(1970, 1, 1)) * INT64CONST(86400));#else			utime = dt + (date0 - date2j(1970, 1, 1)) * SECS_PER_DAY;#endif#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)			tx = localtime(&utime);			tm->tm_year = tx->tm_year + 1900;			tm->tm_mon = tx->tm_mon + 1;			tm->tm_mday = tx->tm_mday;			tm->tm_hour = tx->tm_hour;			tm->tm_min = tx->tm_min;			tm->tm_isdst = tx->tm_isdst;#if defined(HAVE_TM_ZONE)			tm->tm_gmtoff = tx->tm_gmtoff;			tm->tm_zone = tx->tm_zone;			*tzp = -tm->tm_gmtoff;		/* tm_gmtoff is Sun/DEC-ism */			if (tzn != NULL)				*tzn = (char *) tm->tm_zone;#elif defined(HAVE_INT_TIMEZONE)			*tzp = (tm->tm_isdst > 0) ? TIMEZONE_GLOBAL - SECS_PER_HOUR : TIMEZONE_GLOBAL;			if (tzn != NULL)				*tzn = TZNAME_GLOBAL[(tm->tm_isdst > 0)];#endif#else							/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */			*tzp = 0;			/* Mark this as *no* time zone available */			tm->tm_isdst = -1;			if (tzn != NULL)				*tzn = NULL;#endif			dt = dt2local(dt, *tzp);		}		else		{			*tzp = 0;			/* Mark this as *no* time zone available */			tm->tm_isdst = -1;			if (tzn != NULL)				*tzn = NULL;		}	}	else	{		tm->tm_isdst = -1;		if (tzn != NULL)			*tzn = NULL;	}	return 0;}	/* timestamp2tm() *//* EncodeSpecialTimestamp() *	* Convert reserved timestamp data type to string. *	 */static intEncodeSpecialTimestamp(timestamp dt, char *str){	if (TIMESTAMP_IS_NOBEGIN(dt))		strcpy(str, EARLY);	else if (TIMESTAMP_IS_NOEND(dt))		strcpy(str, LATE);	else		return FALSE;	return TRUE;}	/* EncodeSpecialTimestamp() */timestampPGTYPEStimestamp_from_asc(char *str, char **endptr){	timestamp	result;#ifdef HAVE_INT64_TIMESTAMP	int64		noresult = 0;#else	double		noresult = 0.0;#endif	fsec_t		fsec;	struct tm	tt,			   *tm = &tt;	int			tz;	int			dtype;	int			nf;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		lowstr[MAXDATELEN + MAXDATEFIELDS];	char	   *realptr;	char	  **ptr = (endptr != NULL) ? endptr : &realptr;	if (strlen(str) >= sizeof(lowstr))	{		errno = PGTYPES_TS_BAD_TIMESTAMP;		return (noresult);	}	if (ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0 ||		DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tz, 0) != 0)	{		errno = PGTYPES_TS_BAD_TIMESTAMP;		return (noresult);	}	switch (dtype)	{		case DTK_DATE:			if (tm2timestamp(tm, fsec, NULL, &result) != 0)			{				errno = PGTYPES_TS_BAD_TIMESTAMP;				return (noresult);			}			break;		case DTK_EPOCH:			result = SetEpochTimestamp();			break;		case DTK_LATE:			TIMESTAMP_NOEND(result);			break;		case DTK_EARLY:			TIMESTAMP_NOBEGIN(result);			break;		case DTK_INVALID:			errno = PGTYPES_TS_BAD_TIMESTAMP;			return (noresult);		default:			errno = PGTYPES_TS_BAD_TIMESTAMP;			return (noresult);	}	/* AdjustTimestampForTypmod(&result, typmod); */	/*	 * Since it's difficult to test for noresult, make sure errno is 0 if no	 * error occured.	 */	errno = 0;	return result;}char *PGTYPEStimestamp_to_asc(timestamp tstamp){	struct tm	tt,			   *tm = &tt;	char		buf[MAXDATELEN + 1];	char	   *tzn = NULL;	fsec_t		fsec;	int			DateStyle = 1;	/* this defaults to ISO_DATES, shall we make								 * it an option? */	if (TIMESTAMP_NOT_FINITE(tstamp))		EncodeSpecialTimestamp(tstamp, buf);	else if (timestamp2tm(tstamp, NULL, tm, &fsec, NULL) == 0)		EncodeDateTime(tm, fsec, NULL, &tzn, DateStyle, buf, 0);	else	{		errno = PGTYPES_TS_BAD_TIMESTAMP;		return NULL;	}	return pgtypes_strdup(buf);}voidPGTYPEStimestamp_current(timestamp * ts){	struct tm	tm;	GetCurrentDateTime(&tm);	tm2timestamp(&tm, 0, NULL, ts);	return;}static intdttofmtasc_replace(timestamp * ts, date dDate, int dow, struct tm * tm,				   char *output, int *pstr_len, char *fmtstr){	union un_fmt_comb replace_val;	int			replace_type;	int			i;	char	   *p = fmtstr;	char	   *q = output;	while (*p)	{		if (*p == '%')		{			p++;			/* fix compiler warning */			replace_type = PGTYPES_TYPE_NOTHING;			switch (*p)			{				case 'a':					replace_val.str_val = pgtypes_date_weekdays_short[dow];					replace_type = PGTYPES_TYPE_STRING_CONSTANT;					break;				case 'A':					replace_val.str_val = days[dow];					replace_type = PGTYPES_TYPE_STRING_CONSTANT;					break;				case 'b':				case 'h':					replace_val.str_val = months[tm->tm_mon];					replace_type = PGTYPES_TYPE_STRING_CONSTANT;					break;				case 'B':					replace_val.str_val = pgtypes_date_months[tm->tm_mon];					replace_type = PGTYPES_TYPE_STRING_CONSTANT;					break;				case 'c':					/* XXX */					break;				case 'C':					replace_val.uint_val = tm->tm_year / 100;					replace_type = PGTYPES_TYPE_UINT_2_LZ;					break;				case 'd':					replace_val.uint_val = tm->tm_mday;					replace_type = PGTYPES_TYPE_UINT_2_LZ;					break;				case 'D':					/*					 * ts, dDate, dow, tm is information about the timestamp					 *					 * q is the start of the current output buffer					 *					 * pstr_len is a pointer to the remaining size of output,					 * i.e. the size of q					 */					i = dttofmtasc_replace(ts, dDate, dow, tm,										   q, pstr_len,										   "%m/%d/%y");					if (i)						return i;					break;				case 'e':					replace_val.uint_val = tm->tm_mday;					replace_type = PGTYPES_TYPE_UINT_2_LS;					break;				case 'E':

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -