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

📄 datetime.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
					case DOW:						tm->tm_wday = val;						break;					case UNITS:						tmask = 0;						ptype = val;						break;					case ISOTIME:						/*						 * This is a filler field "t" indicating that the next						 * field is time. Try to verify that this is sensible.						 */						tmask = 0;						/* No preceding date? Then quit... */						if ((fmask & DTK_DATE_M) != DTK_DATE_M)							return DTERR_BAD_FORMAT;						/***						 * We will need one of the following fields:						 *	DTK_NUMBER should be hhmmss.fff						 *	DTK_TIME should be hh:mm:ss.fff						 *	DTK_DATE should be hhmmss-zz						 ***/						if (i >= nf - 1 ||							(ftype[i + 1] != DTK_NUMBER &&							 ftype[i + 1] != DTK_TIME &&							 ftype[i + 1] != DTK_DATE))							return DTERR_BAD_FORMAT;						ptype = val;						break;					default:						return DTERR_BAD_FORMAT;				}				break;			default:				return DTERR_BAD_FORMAT;		}		if (tmask & fmask)			return DTERR_BAD_FORMAT;		fmask |= tmask;	}	if (fmask & DTK_M(YEAR))	{		/* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */		if (bc)		{			if (tm->tm_year > 0)				tm->tm_year = -(tm->tm_year - 1);			else				ereport(ERROR,						(errcode(ERRCODE_INVALID_DATETIME_FORMAT),						 errmsg("inconsistent use of year %04d and \"BC\"",								tm->tm_year)));		}		else if (is2digits)		{			if (tm->tm_year < 70)				tm->tm_year += 2000;			else if (tm->tm_year < 100)				tm->tm_year += 1900;		}	}	/* now that we have correct year, decode DOY */	if (fmask & DTK_M(DOY))	{		j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,			   &tm->tm_year, &tm->tm_mon, &tm->tm_mday);	}	/* check for valid month */	if (fmask & DTK_M(MONTH))	{		if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)			return DTERR_MD_FIELD_OVERFLOW;	}	/* minimal check for valid day */	if (fmask & DTK_M(DAY))	{		if (tm->tm_mday < 1 || tm->tm_mday > 31)			return DTERR_MD_FIELD_OVERFLOW;	}	if (mer != HR24 && tm->tm_hour > 12)		return DTERR_FIELD_OVERFLOW;	if (mer == AM && tm->tm_hour == 12)		tm->tm_hour = 0;	else if (mer == PM && tm->tm_hour != 12)		tm->tm_hour += 12;	/* do additional checking for full date specs... */	if (*dtype == DTK_DATE)	{		if ((fmask & DTK_DATE_M) != DTK_DATE_M)		{			if ((fmask & DTK_TIME_M) == DTK_TIME_M)				return 1;			return DTERR_BAD_FORMAT;		}		/*		 * Check for valid day of month, now that we know for sure the month		 * and year.  Note we don't use MD_FIELD_OVERFLOW here, since it seems		 * unlikely that "Feb 29" is a YMD-order error.		 */		if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])			return DTERR_FIELD_OVERFLOW;		/* timezone not specified? then find local timezone if possible */		if (tzp != NULL && !(fmask & DTK_M(TZ)))		{			/*			 * daylight savings time modifier but no standard timezone? then			 * error			 */			if (fmask & DTK_M(DTZMOD))				return DTERR_BAD_FORMAT;			*tzp = DetermineTimeZoneOffset(tm, global_timezone);		}	}	return 0;}/* DetermineTimeZoneOffset() * * Given a struct pg_tm in which tm_year, tm_mon, tm_mday, tm_hour, tm_min, and * tm_sec fields are set, attempt to determine the applicable time zone * (ie, regular or daylight-savings time) at that time.  Set the struct pg_tm's * tm_isdst field accordingly, and return the actual timezone offset. * * Note: it might seem that we should use mktime() for this, but bitter * experience teaches otherwise.  This code is much faster than most versions * of mktime(), anyway. */intDetermineTimeZoneOffset(struct pg_tm * tm, pg_tz *tzp){	int			date,				sec;	pg_time_t	day,				mytime,				prevtime,				boundary,				beforetime,				aftertime;	long int	before_gmtoff,				after_gmtoff;	int			before_isdst,				after_isdst;	int			res;	if (tzp == global_timezone && HasCTZSet)	{		tm->tm_isdst = 0;		/* for lack of a better idea */		return CTimeZone;	}	/*	 * First, generate the pg_time_t value corresponding to the given	 * y/m/d/h/m/s taken as GMT time.  If this overflows, punt and decide the	 * timezone is GMT.  (We only need to worry about overflow on machines	 * where pg_time_t is 32 bits.)	 */	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))		goto overflow;	date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE;	day = ((pg_time_t) date) * SECS_PER_DAY;	if (day / SECS_PER_DAY != date)		goto overflow;	sec = tm->tm_sec + (tm->tm_min + tm->tm_hour * MINS_PER_HOUR) * SECS_PER_MINUTE;	mytime = day + sec;	/* since sec >= 0, overflow could only be from +day to -mytime */	if (mytime < 0 && day > 0)		goto overflow;	/*	 * Find the DST time boundary just before or following the target time. We	 * assume that all zones have GMT offsets less than 24 hours, and that DST	 * boundaries can't be closer together than 48 hours, so backing up 24	 * hours and finding the "next" boundary will work.	 */	prevtime = mytime - SECS_PER_DAY;	if (mytime < 0 && prevtime > 0)		goto overflow;	res = pg_next_dst_boundary(&prevtime,							   &before_gmtoff, &before_isdst,							   &boundary,							   &after_gmtoff, &after_isdst,							   tzp);	if (res < 0)		goto overflow;			/* failure? */	if (res == 0)	{		/* Non-DST zone, life is simple */		tm->tm_isdst = before_isdst;		return -(int) before_gmtoff;	}	/*	 * Form the candidate pg_time_t values with local-time adjustment	 */	beforetime = mytime - before_gmtoff;	if ((before_gmtoff > 0 &&		 mytime < 0 && beforetime > 0) ||		(before_gmtoff <= 0 &&		 mytime > 0 && beforetime < 0))		goto overflow;	aftertime = mytime - after_gmtoff;	if ((after_gmtoff > 0 &&		 mytime < 0 && aftertime > 0) ||		(after_gmtoff <= 0 &&		 mytime > 0 && aftertime < 0))		goto overflow;	/*	 * If both before or both after the boundary time, we know what to do	 */	if (beforetime <= boundary && aftertime < boundary)	{		tm->tm_isdst = before_isdst;		return -(int) before_gmtoff;	}	if (beforetime > boundary && aftertime >= boundary)	{		tm->tm_isdst = after_isdst;		return -(int) after_gmtoff;	}	/*	 * It's an invalid or ambiguous time due to timezone transition. Prefer	 * the standard-time interpretation.	 */	if (after_isdst == 0)	{		tm->tm_isdst = after_isdst;		return -(int) after_gmtoff;	}	tm->tm_isdst = before_isdst;	return -(int) before_gmtoff;overflow:	/* Given date is out of range, so assume UTC */	tm->tm_isdst = 0;	return 0;}/* DecodeTimeOnly() * Interpret parsed string as time fields only. * Returns 0 if successful, DTERR code if bogus input detected. * * Note that support for time zone is here for * SQL92 TIME WITH TIME ZONE, but it reveals * bogosity with SQL92 date/time standards, since * we must infer a time zone from current time. * - thomas 2000-03-10 * Allow specifying date to get a better time zone, * if time zones are allowed. - thomas 2001-12-26 */intDecodeTimeOnly(char **field, int *ftype, int nf,			   int *dtype, struct pg_tm * tm, fsec_t *fsec, int *tzp){	int			fmask = 0,				tmask,				type;	int			ptype = 0;		/* "prefix type" for ISO h04mm05s06 format */	int			i;	int			val;	int			dterr;	int			is2digits = FALSE;	int			mer = HR24;	*dtype = DTK_TIME;	tm->tm_hour = 0;	tm->tm_min = 0;	tm->tm_sec = 0;	*fsec = 0;	/* don't know daylight savings time status apriori */	tm->tm_isdst = -1;	if (tzp != NULL)		*tzp = 0;	for (i = 0; i < nf; i++)	{		switch (ftype[i])		{			case DTK_DATE:				/*				 * Time zone not allowed? Then should not accept dates or time				 * zones no matter what else!				 */				if (tzp == NULL)					return DTERR_BAD_FORMAT;				/* Under limited circumstances, we will accept a date... */				if (i == 0 && nf >= 2 &&					(ftype[nf - 1] == DTK_DATE || ftype[1] == DTK_TIME))				{					dterr = DecodeDate(field[i], fmask, &tmask, tm);					if (dterr)						return dterr;				}				/* otherwise, this is a time and/or time zone */				else				{					if (isdigit((unsigned char) *field[i]))					{						char	   *cp;						/*						 * Starts with a digit but we already have a time						 * field? Then we are in trouble with time already...						 */						if ((fmask & DTK_TIME_M) == DTK_TIME_M)							return DTERR_BAD_FORMAT;						/*						 * Should not get here and fail. Sanity check only...						 */						if ((cp = strchr(field[i], '-')) == NULL)							return DTERR_BAD_FORMAT;						/* Get the time zone from the end of the string */						dterr = DecodeTimezone(cp, tzp);						if (dterr)							return dterr;						*cp = '\0';						/*						 * Then read the rest of the field as a concatenated						 * time						 */						dterr = DecodeNumberField(strlen(field[i]), field[i],												  (fmask | DTK_DATE_M),												  &tmask, tm,												  fsec, &is2digits);						if (dterr < 0)							return dterr;						ftype[i] = dterr;						tmask |= DTK_M(TZ);					}					else					{						dterr = DecodePosixTimezone(field[i], tzp);						if (dterr)							return dterr;						ftype[i] = DTK_TZ;						tmask = DTK_M(TZ);					}				}				break;			case DTK_TIME:				dterr = DecodeTime(field[i], (fmask | DTK_DATE_M),								   &tmask, tm, fsec);				if (dterr)					return dterr;				break;			case DTK_TZ:				{					int			tz;					if (tzp == NULL)						return DTERR_BAD_FORMAT;					dterr = DecodeTimezone(field[i], &tz);					if (dterr)						return dterr;					/*					 * Already have a time zone? Then maybe this is the second					 * field of a POSIX time: EST+3 (equivalent to PST)					 */					if (i > 0 && (fmask & DTK_M(TZ)) != 0 &&						ftype[i - 1] == DTK_TZ &&						isalpha((unsigned char) *field[i - 1]))					{						*tzp -= tz;						tmask = 0;					}					else					{						*tzp = tz;						tmask = DTK_M(TZ);					}				}				break;			case DTK_NUMBER:				/*				 * Was this an "ISO time" with embedded field labels? An				 * example is "h04m05s06" - thomas 2001-02-04				 */				if (ptype != 0)				{					char	   *cp;					int			val;					/* Only accept a date under limited circumstances */					switch (ptype)					{						case DTK_JULIAN:						case DTK_YEAR:						case DTK_MONTH:						case DTK_DAY:							if (tzp == NULL)								return DTERR_BAD_FORMAT;						default:							break;					}					errno = 0;					val = strtol(field[i], &cp, 10);					if (errno == ERANGE)						return DTERR_FIELD_OVERFLOW;					/*					 * only a few kinds are allowed to have an embedded					 * decimal					 */					if (*cp == '.')						switch (ptype)						{							case DTK_JULIAN:							case DTK_TIME:							case DTK_SECOND:								break;							default:								return DTERR_BAD_FORMAT;								break;						}					else if (*cp != '\0')						return DTERR_BAD_FORMAT;					switch (ptype)					{						case DTK_YEAR:							tm->tm_year = val;							tmask = DTK_M(YEAR);							break;						case DTK_MONTH:							/*							 * already have a month and hour? then assume							 * minutes							 */							if ((fmask & DTK_M(MONTH)) != 0 &&								(fmask & DTK_M(HOUR)) != 0)							{								tm->tm_min = val;								tmask = DTK_M(MINUTE);							}							else							{								tm->tm_mon = val;								tmask = DTK_M(MONTH);							}							break;						case DTK_DAY:							tm->tm_mday = val;							tmask = DTK_M(DAY);							break;						case DTK_HOUR:							tm->tm_hour = val;							tmask = DTK_M(HOUR);							break;						case DTK_MINUTE:							tm->tm_min = val;

⌨️ 快捷键说明

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