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

📄 interval.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $PostgreSQL: pgsql/src/interfaces/ecpg/pgtypeslib/interval.c,v 1.37 2007/08/22 08:20:58 meskes Exp $ */#include "postgres_fe.h"#include <time.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_error.h"#include "pgtypes_interval.h"/* DecodeInterval() * Interpret previously parsed fields for general time interval. * Return 0 if decoded and -1 if problems. * * Allow "date" field DTK_DATE since this could be just *	an unsigned floating point number. - thomas 1997-11-16 * * Allow ISO-style time span, with implicit units on number of days *	preceding an hh:mm:ss field. - thomas 1998-04-30 */intDecodeInterval(char **field, int *ftype, int nf, int *dtype, struct tm * tm, fsec_t *fsec){	int			is_before = FALSE;	char	   *cp;	int			fmask = 0,				tmask,				type;	int			i;	int			val;	double		fval;	*dtype = DTK_DELTA;	type = IGNORE_DTF;	tm->tm_year = 0;	tm->tm_mon = 0;	tm->tm_mday = 0;	tm->tm_hour = 0;	tm->tm_min = 0;	tm->tm_sec = 0;	*fsec = 0;	/* read through list backwards to pick up units before values */	for (i = nf - 1; i >= 0; i--)	{		switch (ftype[i])		{			case DTK_TIME:				if (DecodeTime(field[i], fmask, &tmask, tm, fsec) != 0)					return -1;				type = DTK_DAY;				break;			case DTK_TZ:				/*				 * Timezone is a token with a leading sign character and				 * otherwise the same as a non-signed time field				 */				/*				 * A single signed number ends up here, but will be rejected				 * by DecodeTime(). So, work this out to drop through to				 * DTK_NUMBER, which *can* tolerate this.				 */				cp = field[i] + 1;				while (*cp != '\0' && *cp != ':' && *cp != '.')					cp++;				if (*cp == ':' && DecodeTime((field[i] + 1), fmask, &tmask, tm, fsec) == 0)				{					if (*field[i] == '-')					{						/* flip the sign on all fields */						tm->tm_hour = -tm->tm_hour;						tm->tm_min = -tm->tm_min;						tm->tm_sec = -tm->tm_sec;						*fsec = -(*fsec);					}					/*					 * Set the next type to be a day, if units are not					 * specified. This handles the case of '1 +02:03' since we					 * are reading right to left.					 */					type = DTK_DAY;					tmask = DTK_M(TZ);					break;				}				else if (type == IGNORE_DTF)				{					if (*cp == '.')					{						/*						 * Got a decimal point? Then assume some sort of						 * seconds specification						 */						type = DTK_SECOND;					}					else if (*cp == '\0')					{						/*						 * Only a signed integer? Then must assume a						 * timezone-like usage						 */						type = DTK_HOUR;					}				}				/* DROP THROUGH */			case DTK_DATE:			case DTK_NUMBER:				val = strtol(field[i], &cp, 10);				if (type == IGNORE_DTF)					type = DTK_SECOND;				if (*cp == '.')				{					fval = strtod(cp, &cp);					if (*cp != '\0')						return -1;					if (val < 0)						fval = -fval;				}				else if (*cp == '\0')					fval = 0;				else					return -1;				tmask = 0;		/* DTK_M(type); */				switch (type)				{					case DTK_MICROSEC:#ifdef HAVE_INT64_TIMESTAMP						*fsec += val + fval;#else						*fsec += (val + fval) * 1e-6;#endif						break;					case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP						*fsec += (val + fval) * 1000;#else						*fsec += (val + fval) * 1e-3;#endif						break;					case DTK_SECOND:						tm->tm_sec += val;#ifdef HAVE_INT64_TIMESTAMP						*fsec += fval * 1000000;#else						*fsec += fval;#endif						tmask = DTK_M(SECOND);						break;					case DTK_MINUTE:						tm->tm_min += val;						if (fval != 0)						{							int			sec;							fval *= SECS_PER_MINUTE;							sec = fval;							tm->tm_sec += sec;#ifdef HAVE_INT64_TIMESTAMP							*fsec += ((fval - sec) * 1000000);#else							*fsec += fval - sec;#endif						}						tmask = DTK_M(MINUTE);						break;					case DTK_HOUR:						tm->tm_hour += val;						if (fval != 0)						{							int			sec;							fval *= SECS_PER_HOUR;							sec = fval;							tm->tm_sec += sec;#ifdef HAVE_INT64_TIMESTAMP							*fsec += (fval - sec) * 1000000;#else							*fsec += fval - sec;#endif						}						tmask = DTK_M(HOUR);						break;					case DTK_DAY:						tm->tm_mday += val;						if (fval != 0)						{							int			sec;							fval *= SECS_PER_DAY;							sec = fval;							tm->tm_sec += sec;#ifdef HAVE_INT64_TIMESTAMP							*fsec += (fval - sec) * 1000000;#else							*fsec += fval - sec;#endif						}						tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);						break;					case DTK_WEEK:						tm->tm_mday += val * 7;						if (fval != 0)						{							int			extra_days;							fval *= 7;							extra_days = (int32) fval;							tm->tm_mday += extra_days;							fval -= extra_days;							if (fval != 0)							{								int			sec;								fval *= SECS_PER_DAY;								sec = fval;								tm->tm_sec += sec;#ifdef HAVE_INT64_TIMESTAMP								*fsec += (fval - sec) * 1000000;#else								*fsec += fval - sec;#endif							}						}						tmask = (fmask & DTK_M(DAY)) ? 0 : DTK_M(DAY);						break;					case DTK_MONTH:						tm->tm_mon += val;						if (fval != 0)						{							int			day;							fval *= DAYS_PER_MONTH;							day = fval;							tm->tm_mday += day;							fval -= day;							if (fval != 0)							{								int			sec;								fval *= SECS_PER_DAY;								sec = fval;								tm->tm_sec += sec;#ifdef HAVE_INT64_TIMESTAMP								*fsec += (fval - sec) * 1000000;#else								*fsec += fval - sec;#endif							}						}						tmask = DTK_M(MONTH);						break;					case DTK_YEAR:						tm->tm_year += val;						if (fval != 0)							tm->tm_mon += fval * MONTHS_PER_YEAR;						tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);						break;					case DTK_DECADE:						tm->tm_year += val * 10;						if (fval != 0)							tm->tm_mon += fval * MONTHS_PER_YEAR * 10;						tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);						break;					case DTK_CENTURY:						tm->tm_year += val * 100;						if (fval != 0)							tm->tm_mon += fval * MONTHS_PER_YEAR * 100;						tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);						break;					case DTK_MILLENNIUM:						tm->tm_year += val * 1000;						if (fval != 0)							tm->tm_mon += fval * MONTHS_PER_YEAR * 1000;						tmask = (fmask & DTK_M(YEAR)) ? 0 : DTK_M(YEAR);						break;					default:						return -1;				}				break;			case DTK_STRING:			case DTK_SPECIAL:				type = DecodeUnits(i, field[i], &val);				if (type == IGNORE_DTF)					continue;				tmask = 0;		/* DTK_M(type); */				switch (type)				{					case UNITS:						type = val;						break;					case AGO:						is_before = TRUE;						type = val;						break;					case RESERV:						tmask = (DTK_DATE_M || DTK_TIME_M);						*dtype = val;						break;					default:						return -1;				}				break;			default:				return -1;		}		if (tmask & fmask)			return -1;		fmask |= tmask;	}	if (*fsec != 0)	{		int			sec;#ifdef HAVE_INT64_TIMESTAMP		sec = *fsec / USECS_PER_SEC;		*fsec -= sec * USECS_PER_SEC;#else		TMODULO(*fsec, sec, 1.0);#endif		tm->tm_sec += sec;	}	if (is_before)	{		*fsec = -(*fsec);		tm->tm_sec = -(tm->tm_sec);		tm->tm_min = -(tm->tm_min);		tm->tm_hour = -(tm->tm_hour);		tm->tm_mday = -(tm->tm_mday);		tm->tm_mon = -(tm->tm_mon);		tm->tm_year = -(tm->tm_year);	}	/* ensure that at least one time field has been found */	return (fmask != 0) ? 0 : -1;}	/* DecodeInterval() *//* EncodeInterval() * Interpret time structure as a delta time and convert to string. * * Support "traditional Postgres" and ISO-8601 styles. * Actually, afaik ISO does not address time interval formatting, *	but this looks similar to the spec for absolute date/time. * - thomas 1998-04-30 */intEncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str){	int			is_before = FALSE;	int			is_nonzero = FALSE;	char	   *cp = str;	/*	 * The sign of year and month are guaranteed to match, since they are	 * stored internally as "month". But we'll need to check for is_before and

⌨️ 快捷键说明

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