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

📄 dt_common.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidabstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn){	time_t		time = (time_t) _time;	struct tm  *tx;	if (tzp != NULL)		tx = localtime((time_t *) &time);	else		tx = gmtime((time_t *) &time);	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_sec = tx->tm_sec;	tm->tm_isdst = tx->tm_isdst;#if defined(HAVE_TM_ZONE)	tm->tm_gmtoff = tx->tm_gmtoff;	tm->tm_zone = tx->tm_zone;	if (tzp != NULL)	{		/*		 * We have a brute force time zone per SQL99? Then use it without		 * change since we have already rotated to the time zone.		 */		*tzp = -tm->tm_gmtoff;	/* tm_gmtoff is Sun/DEC-ism */		/*		 * XXX FreeBSD man pages indicate that this should work - tgl 97/04/23		 */		if (tzn != NULL)		{			/*			 * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it			 * contains an error message, which doesn't fit in the buffer			 */			StrNCpy(*tzn, tm->tm_zone, MAXTZLEN + 1);			if (strlen(tm->tm_zone) > MAXTZLEN)				tm->tm_isdst = -1;		}	}	else		tm->tm_isdst = -1;#elif defined(HAVE_INT_TIMEZONE)	if (tzp != NULL)	{		*tzp = (tm->tm_isdst > 0) ? TIMEZONE_GLOBAL - SECS_PER_HOUR : TIMEZONE_GLOBAL;		if (tzn != NULL)		{			/*			 * Copy no more than MAXTZLEN bytes of timezone to tzn, in case it			 * contains an error message, which doesn't fit in the buffer			 */			StrNCpy(*tzn, TZNAME_GLOBAL[tm->tm_isdst], MAXTZLEN + 1);			if (strlen(TZNAME_GLOBAL[tm->tm_isdst]) > MAXTZLEN)				tm->tm_isdst = -1;		}	}	else		tm->tm_isdst = -1;#else							/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */	if (tzp != NULL)	{		/* default to UTC */		*tzp = 0;		if (tzn != NULL)			*tzn = NULL;	}	else		tm->tm_isdst = -1;#endif}voidGetCurrentDateTime(struct tm * tm){	int			tz;	abstime2tm(time(NULL), &tz, tm, NULL);}/* DetermineLocalTimeZone() * * Given a struct tm in which tm_year, tm_mon, tm_mday, tm_hour, tm_min, and * tm_sec fields are set, attempt to determine the applicable local zone * (ie, regular or daylight-savings time) at that time.  Set the struct tm's * tm_isdst field accordingly, and return the actual timezone offset. * * This subroutine exists to centralize uses of mktime() and defend against * mktime() bugs/restrictions on various platforms.  This should be * the *only* call of mktime() in the backend. */static intDetermineLocalTimeZone(struct tm * tm){	int			tz;	if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))	{#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)		/*		 * Some buggy mktime() implementations may change the year/month/day		 * when given a time right at a DST boundary.  To prevent corruption		 * of the caller's data, give mktime() a copy...		 */		struct tm	tt,				   *tmp = &tt;		*tmp = *tm;		/* change to Unix conventions for year/month */		tmp->tm_year -= 1900;		tmp->tm_mon -= 1;		/* indicate timezone unknown */		tmp->tm_isdst = -1;		if (mktime(tmp) != (time_t) -1 && tmp->tm_isdst >= 0)		{			/* mktime() succeeded, trust its result */			tm->tm_isdst = tmp->tm_isdst;#if defined(HAVE_TM_ZONE)			/* tm_gmtoff is Sun/DEC-ism */			tz = -tmp->tm_gmtoff;#elif defined(HAVE_INT_TIMEZONE)			tz = (tmp->tm_isdst > 0) ? TIMEZONE_GLOBAL - SECS_PER_HOUR : TIMEZONE_GLOBAL;#endif   /* HAVE_INT_TIMEZONE */		}		else		{			/*			 * We have a buggy (not to say deliberately brain damaged)			 * mktime().  Work around it by using localtime() instead.			 *			 * First, generate the time_t value corresponding to the given			 * y/m/d/h/m/s taken as GMT time.  This will not overflow (at			 * least not for time_t taken as signed) because of the range			 * check we did above.			 */			long		day,						mysec,						locsec,						delta1,						delta2;			time_t		mytime;			day = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) -				   date2j(1970, 1, 1));			mysec = tm->tm_sec + (tm->tm_min + (day * HOURS_PER_DAY + tm->tm_hour) * MINS_PER_HOUR) * SECS_PER_MINUTE;			mytime = (time_t) mysec;			/*			 * Use localtime to convert that time_t to broken-down time, and			 * reassemble to get a representation of local time.			 */			tmp = localtime(&mytime);			day = (date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) -				   date2j(1970, 1, 1));			locsec = tmp->tm_sec + (tmp->tm_min + (day * HOURS_PER_DAY + tmp->tm_hour) * MINS_PER_HOUR) * SECS_PER_MINUTE;			/*			 * The local time offset corresponding to that GMT time is now			 * computable as mysec - locsec.			 */			delta1 = mysec - locsec;			/*			 * However, if that GMT time and the local time we are actually			 * interested in are on opposite sides of a daylight-savings-time			 * transition, then this is not the time offset we want.  So,			 * adjust the time_t to be what we think the GMT time			 * corresponding to our target local time is, and repeat the			 * localtime() call and delta calculation.	We may have to do it			 * twice before we have a trustworthy delta.			 *			 * Note: think not to put a loop here, since if we've been given			 * an "impossible" local time (in the gap during a spring-forward			 * transition) we'd never get out of the loop. Twice is enough to			 * give the behavior we want, which is that "impossible" times are			 * taken as standard time, while at a fall-back boundary ambiguous			 * times are also taken as standard.			 */			mysec += delta1;			mytime = (time_t) mysec;			tmp = localtime(&mytime);			day = (date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) -				   date2j(1970, 1, 1));			locsec = tmp->tm_sec + (tmp->tm_min + (day * HOURS_PER_DAY + tmp->tm_hour) * MINS_PER_HOUR) * SECS_PER_MINUTE;			delta2 = mysec - locsec;			if (delta2 != delta1)			{				mysec += (delta2 - delta1);				mytime = (time_t) mysec;				tmp = localtime(&mytime);				day = (date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) -					   date2j(1970, 1, 1));				locsec = tmp->tm_sec + (tmp->tm_min + (day * HOURS_PER_DAY + tmp->tm_hour) * MINS_PER_HOUR) * SECS_PER_MINUTE;				delta2 = mysec - locsec;			}			tm->tm_isdst = tmp->tm_isdst;			tz = (int) delta2;		}#else							/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */		/* Assume UTC if no system timezone info available */		tm->tm_isdst = 0;		tz = 0;#endif	}	else	{		/* Given date is out of range, so assume UTC */		tm->tm_isdst = 0;		tz = 0;	}	return tz;}static voiddt2time(double 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);#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() *//* DecodeNumberField() * Interpret numeric string as a concatenated date or time field. * Use the context of previously decoded fields to help with * the interpretation. */static intDecodeNumberField(int len, char *str, int fmask,	int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits, bool EuroDates){	char	   *cp;	/*	 * Have a decimal point? Then this is a date or something with a seconds	 * field...	 */	if ((cp = strchr(str, '.')) != NULL)	{#ifdef HAVE_INT64_TIMESTAMP		char		fstr[MAXDATELEN + 1];		/*		 * OK, we have at most six digits to care about. Let's construct a		 * string and then do the conversion to an integer.		 */		strcpy(fstr, (cp + 1));		strcpy(fstr + strlen(fstr), "000000");		*(fstr + 6) = '\0';		*fsec = strtol(fstr, NULL, 10);#else		*fsec = strtod(cp, NULL);#endif		*cp = '\0';		len = strlen(str);	}	/* No decimal point and no complete date yet? */	else if ((fmask & DTK_DATE_M) != DTK_DATE_M)	{		/* yyyymmdd? */		if (len == 8)		{			*tmask = DTK_DATE_M;			tm->tm_mday = atoi(str + 6);			*(str + 6) = '\0';			tm->tm_mon = atoi(str + 4);			*(str + 4) = '\0';			tm->tm_year = atoi(str + 0);			return DTK_DATE;		}		/* yymmdd? */		else if (len == 6)		{			*tmask = DTK_DATE_M;			tm->tm_mday = atoi(str + 4);			*(str + 4) = '\0';			tm->tm_mon = atoi(str + 2);			*(str + 2) = '\0';			tm->tm_year = atoi(str + 0);			*is2digits = TRUE;			return DTK_DATE;		}		/* yyddd? */		else if (len == 5)		{			*tmask = DTK_DATE_M;			tm->tm_mday = atoi(str + 2);			*(str + 2) = '\0';			tm->tm_mon = 1;			tm->tm_year = atoi(str + 0);			*is2digits = TRUE;			return DTK_DATE;		}	}	/* not all time fields are specified? */	if ((fmask & DTK_TIME_M) != DTK_TIME_M)	{		/* hhmmss */		if (len == 6)		{			*tmask = DTK_TIME_M;			tm->tm_sec = atoi(str + 4);			*(str + 4) = '\0';			tm->tm_min = atoi(str + 2);			*(str + 2) = '\0';			tm->tm_hour = atoi(str + 0);			return DTK_TIME;		}		/* hhmm? */		else if (len == 4)		{			*tmask = DTK_TIME_M;			tm->tm_sec = 0;			tm->tm_min = atoi(str + 2);			*(str + 2) = '\0';			tm->tm_hour = atoi(str + 0);			return DTK_TIME;		}	}	return -1;}	/* DecodeNumberField() *//* DecodeNumber() * Interpret plain numeric field as a date value in context. */static intDecodeNumber(int flen, char *str, int fmask,	int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits, bool EuroDates){	int			val;	char	   *cp;	*tmask = 0;	val = strtol(str, &cp, 10);	if (cp == str)		return -1;	if (*cp == '.')	{		/*		 * More than two digits? Then could be a date or a run-together time:		 * 2001.360 20011225 040506.789		 */		if (cp - str > 2)			return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),									 tmask, tm, fsec, is2digits, EuroDates);		*fsec = strtod(cp, &cp);		if (*cp != '\0')			return -1;	}	else if (*cp != '\0')		return -1;	/* Special case day of year? */	if (flen == 3 && (fmask & DTK_M(YEAR)) && val >= 1 && val <= 366)	{		*tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY));		tm->tm_yday = val;		j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,			   &tm->tm_year, &tm->tm_mon, &tm->tm_mday);	}	/***	 * Enough digits to be unequivocal year? Used to test for 4 digits or	 * more, but we now test first for a three-digit doy so anything	 * bigger than two digits had better be an explicit year.	 * - thomas 1999-01-09	 * Back to requiring a 4 digit year. We accept a two digit	 * year farther down. - thomas 2000-03-28	 ***/	else if (flen >= 4)	{		*tmask = DTK_M(YEAR);		/* already have a year? then see if we can substitute... */		if ((fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)) &&			tm->tm_year >= 1 && tm->tm_year <= 31)		{			tm->tm_mday = tm->tm_year;			*tmask = DTK_M(DAY);		}		tm->tm_year = val;	}	/* already have year? then could be month */	else if ((fmask & DTK_M(YEAR)) && !(fmask & DTK_M(MONTH)) && val >= 1 && val <= MONTHS_PER_YEAR)	{		*tmask = DTK_M(MONTH);		tm->tm_mon = val;	}	/* no year and EuroDates enabled? then could be day */	else if ((EuroDates || (fmask & DTK_M(MONTH))) &&			 !(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)) &&			 val >= 1 && val <= 31)	{		*tmask = DTK_M(DAY);		tm->tm_mday = val;	}	else if (!(fmask & DTK_M(MONTH)) && val >= 1 && val <= MONTHS_PER_YEAR)	{		*tmask = DTK_M(MONTH);		tm->tm_mon = val;	}	else if (!(fmask & DTK_M(DAY)) && val >= 1 && val <= 31)	{		*tmask = DTK_M(DAY);		tm->tm_mday = val;	}	/*	 * Check for 2 or 4 or more digits, but currently we reach here only if	 * two digits. - thomas 2000-03-28	 */	else if (!(fmask & DTK_M(YEAR)) && (flen >= 4 || flen == 2))	{		*tmask = DTK_M(YEAR);		tm->tm_year = val;		/* adjust ONLY if exactly two digits... */		*is2digits = (flen == 2);	}	else		return -1;	return 0;}	/* DecodeNumber() *//* DecodeDate() * Decode date string which includes delimiters. * Insist on a complete set of fields. */static intDecodeDate(char *str, int fmask, int *tmask, struct tm * tm, bool EuroDates){	fsec_t		fsec;	int			nf = 0;	int			i,				len;	int			bc = FALSE;	int			is2digits = FALSE;	int			type,				val,				dmask = 0;	char	   *field[MAXDATEFIELDS];	/* parse this string... */	while (*str != '\0' && nf < MAXDATEFIELDS)	{		/* skip field separators */		while (!isalnum((unsigned char) *str))			str++;		field[nf] = str;		if (isdigit((unsigned char) *str))		{			while (isdigit((unsigned char) *str))

⌨️ 快捷键说明

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