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

📄 dt_common.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
				str++;		}		else if (isalpha((unsigned char) *str))		{			while (isalpha((unsigned char) *str))				str++;		}		/* Just get rid of any non-digit, non-alpha characters... */		if (*str != '\0')			*str++ = '\0';		nf++;	}#if 0	/* don't allow too many fields */	if (nf > 3)		return -1;#endif	*tmask = 0;	/* look first for text fields, since that will be unambiguous month */	for (i = 0; i < nf; i++)	{		if (isalpha((unsigned char) *field[i]))		{			type = DecodeSpecial(i, field[i], &val);			if (type == IGNORE_DTF)				continue;			dmask = DTK_M(type);			switch (type)			{				case MONTH:					tm->tm_mon = val;					break;				case ADBC:					bc = (val == BC);					break;				default:					return -1;			}			if (fmask & dmask)				return -1;			fmask |= dmask;			*tmask |= dmask;			/* mark this field as being completed */			field[i] = NULL;		}	}	/* now pick up remaining numeric fields */	for (i = 0; i < nf; i++)	{		if (field[i] == NULL)			continue;		if ((len = strlen(field[i])) <= 0)			return -1;		if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec, &is2digits, EuroDates) != 0)			return -1;		if (fmask & dmask)			return -1;		fmask |= dmask;		*tmask |= dmask;	}	if ((fmask & ~(DTK_M(DOY) | DTK_M(TZ))) != DTK_DATE_M)		return -1;	/* 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			return -1;	}	else if (is2digits)	{		if (tm->tm_year < 70)			tm->tm_year += 2000;		else if (tm->tm_year < 100)			tm->tm_year += 1900;	}	return 0;}	/* DecodeDate() *//* DecodeTime() * Decode time string which includes delimiters. * Only check the lower limit on hours, since this same code *	can be used to represent time spans. */static intDecodeTime(char *str, int fmask, int *tmask, struct tm * tm, fsec_t *fsec){	char	   *cp;	*tmask = DTK_TIME_M;	tm->tm_hour = strtol(str, &cp, 10);	if (*cp != ':')		return -1;	str = cp + 1;	tm->tm_min = strtol(str, &cp, 10);	if (*cp == '\0')	{		tm->tm_sec = 0;		*fsec = 0;	}	else if (*cp != ':')		return -1;	else	{		str = cp + 1;		tm->tm_sec = strtol(str, &cp, 10);		if (*cp == '\0')			*fsec = 0;		else if (*cp == '.')		{#ifdef HAVE_INT64_TIMESTAMP			char		fstr[MAXDATELEN + 1];			/*			 * OK, we have at most six digits to work with. Let's construct a			 * string and then do the conversion to an integer.			 */			strncpy(fstr, (cp + 1), 7);			strcpy(fstr + strlen(fstr), "000000");			*(fstr + 6) = '\0';			*fsec = strtol(fstr, &cp, 10);#else			str = cp;			*fsec = strtod(str, &cp);#endif			if (*cp != '\0')				return -1;		}		else			return -1;	}	/* do a sanity check */#ifdef HAVE_INT64_TIMESTAMP	if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||		tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= USECS_PER_SEC)		return -1;#else	if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||		tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= 1)		return -1;#endif	return 0;}	/* DecodeTime() *//* DecodeTimezone() * Interpret string as a numeric timezone. * * Note: we allow timezone offsets up to 13:59.  There are places that * use +1300 summer time. */static intDecodeTimezone(char *str, int *tzp){	int			tz;	int			hr,				min;	char	   *cp;	int			len;	/* assume leading character is "+" or "-" */	hr = strtol(str + 1, &cp, 10);	/* explicit delimiter? */	if (*cp == ':')		min = strtol(cp + 1, &cp, 10);	/* otherwise, might have run things together... */	else if (*cp == '\0' && (len = strlen(str)) > 3)	{		min = strtol(str + len - 2, &cp, 10);		if (min < 0 || min >= 60)			return -1;		*(str + len - 2) = '\0';		hr = strtol(str + 1, &cp, 10);		if (hr < 0 || hr > 13)			return -1;	}	else		min = 0;	tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE;	if (*str == '-')		tz = -tz;	*tzp = -tz;	return *cp != '\0';}	/* DecodeTimezone() *//* DecodePosixTimezone() * Interpret string as a POSIX-compatible timezone: *	PST-hh:mm *	PST+h * - thomas 2000-03-15 */static intDecodePosixTimezone(char *str, int *tzp){	int			val,				tz;	int			type;	char	   *cp;	char		delim;	cp = str;	while (*cp != '\0' && isalpha((unsigned char) *cp))		cp++;	if (DecodeTimezone(cp, &tz) != 0)		return -1;	delim = *cp;	*cp = '\0';	type = DecodeSpecial(MAXDATEFIELDS - 1, str, &val);	*cp = delim;	switch (type)	{		case DTZ:		case TZ:			*tzp = (val * MINS_PER_HOUR) - tz;			break;		default:			return -1;	}	return 0;}	/* DecodePosixTimezone() *//* ParseDateTime() * Break string into tokens based on a date/time context. * Several field types are assigned: *	DTK_NUMBER - digits and (possibly) a decimal point *	DTK_DATE - digits and two delimiters, or digits and text *	DTK_TIME - digits, colon delimiters, and possibly a decimal point *	DTK_STRING - text (no digits) *	DTK_SPECIAL - leading "+" or "-" followed by text *	DTK_TZ - leading "+" or "-" followed by digits * Note that some field types can hold unexpected items: *	DTK_NUMBER can hold date fields (yy.ddd) *	DTK_STRING can hold months (January) and time zones (PST) *	DTK_DATE can hold Posix time zones (GMT-8) */intParseDateTime(char *timestr, char *lowstr,	  char **field, int *ftype, int maxfields, int *numfields, char **endstr){	int			nf = 0;	char	   *lp = lowstr;	*endstr = timestr;	/* outer loop through fields */	while (*(*endstr) != '\0')	{		field[nf] = lp;		/* leading digit? then date or time */		if (isdigit((unsigned char) *(*endstr)))		{			*lp++ = *(*endstr)++;			while (isdigit((unsigned char) *(*endstr)))				*lp++ = *(*endstr)++;			/* time field? */			if (*(*endstr) == ':')			{				ftype[nf] = DTK_TIME;				*lp++ = *(*endstr)++;				while (isdigit((unsigned char) *(*endstr)) ||					   (*(*endstr) == ':') || (*(*endstr) == '.'))					*lp++ = *(*endstr)++;			}			/* date field? allow embedded text month */			else if (*(*endstr) == '-' || *(*endstr) == '/' || *(*endstr) == '.')			{				/* save delimiting character to use later */				char	   *dp = (*endstr);				*lp++ = *(*endstr)++;				/* second field is all digits? then no embedded text month */				if (isdigit((unsigned char) *(*endstr)))				{					ftype[nf] = (*dp == '.') ? DTK_NUMBER : DTK_DATE;					while (isdigit((unsigned char) *(*endstr)))						*lp++ = *(*endstr)++;					/*					 * insist that the delimiters match to get a three-field					 * date.					 */					if (*(*endstr) == *dp)					{						ftype[nf] = DTK_DATE;						*lp++ = *(*endstr)++;						while (isdigit((unsigned char) *(*endstr)) || (*(*endstr) == *dp))							*lp++ = *(*endstr)++;					}				}				else				{					ftype[nf] = DTK_DATE;					while (isalnum((unsigned char) *(*endstr)) || (*(*endstr) == *dp))						*lp++ = pg_tolower((unsigned char) *(*endstr)++);				}			}			/*			 * otherwise, number only and will determine year, month, day, or			 * concatenated fields later...			 */			else				ftype[nf] = DTK_NUMBER;		}		/* Leading decimal point? Then fractional seconds... */		else if (*(*endstr) == '.')		{			*lp++ = *(*endstr)++;			while (isdigit((unsigned char) *(*endstr)))				*lp++ = *(*endstr)++;			ftype[nf] = DTK_NUMBER;		}		/*		 * text? then date string, month, day of week, special, or timezone		 */		else if (isalpha((unsigned char) *(*endstr)))		{			ftype[nf] = DTK_STRING;			*lp++ = pg_tolower((unsigned char) *(*endstr)++);			while (isalpha((unsigned char) *(*endstr)))				*lp++ = pg_tolower((unsigned char) *(*endstr)++);			/*			 * Full date string with leading text month? Could also be a POSIX			 * time zone...			 */			if (*(*endstr) == '-' || *(*endstr) == '/' || *(*endstr) == '.')			{				char	   *dp = (*endstr);				ftype[nf] = DTK_DATE;				*lp++ = *(*endstr)++;				while (isdigit((unsigned char) *(*endstr)) || *(*endstr) == *dp)					*lp++ = *(*endstr)++;			}		}		/* skip leading spaces */		else if (isspace((unsigned char) *(*endstr)))		{			(*endstr)++;			continue;		}		/* sign? then special or numeric timezone */		else if (*(*endstr) == '+' || *(*endstr) == '-')		{			*lp++ = *(*endstr)++;			/* soak up leading whitespace */			while (isspace((unsigned char) *(*endstr)))				(*endstr)++;			/* numeric timezone? */			if (isdigit((unsigned char) *(*endstr)))			{				ftype[nf] = DTK_TZ;				*lp++ = *(*endstr)++;				while (isdigit((unsigned char) *(*endstr)) ||					   (*(*endstr) == ':') || (*(*endstr) == '.'))					*lp++ = *(*endstr)++;			}			/* special? */			else if (isalpha((unsigned char) *(*endstr)))			{				ftype[nf] = DTK_SPECIAL;				*lp++ = pg_tolower((unsigned char) *(*endstr)++);				while (isalpha((unsigned char) *(*endstr)))					*lp++ = pg_tolower((unsigned char) *(*endstr)++);			}			/* otherwise something wrong... */			else				return -1;		}		/* ignore punctuation but use as delimiter */		else if (ispunct((unsigned char) *(*endstr)))		{			(*endstr)++;			continue;		}		/* otherwise, something is not right... */		else			return -1;		/* force in a delimiter after each field */		*lp++ = '\0';		nf++;		if (nf > MAXDATEFIELDS)			return -1;	}	*numfields = nf;	return 0;}	/* ParseDateTime() *//* DecodeDateTime() * Interpret previously parsed fields for general date and time. * Return 0 if full date, 1 if only time, and -1 if problems. *		External format(s): *				"<weekday> <month>-<day>-<year> <hour>:<minute>:<second>" *				"Fri Feb-7-1997 15:23:27" *				"Feb-7-1997 15:23:27" *				"2-7-1997 15:23:27" *				"1997-2-7 15:23:27" *				"1997.038 15:23:27"		(day of year 1-366) *		Also supports input in compact time: *				"970207 152327" *				"97038 152327" *				"20011225T040506.789-07" * * Use the system-provided functions to get the current time zone *	if not specified in the input string. * If the date is outside the time_t system-supported time range, *	then assume UTC time zone. - thomas 1997-05-27 */intDecodeDateTime(char **field, int *ftype, int nf,		  int *dtype, struct tm * tm, fsec_t *fsec, int *tzp, bool EuroDates){	int			fmask = 0,				tmask,				type;	int			ptype = 0;		/* "prefix type" for ISO y2001m02d04 format */	int			i;	int			val;	int			mer = HR24;	int			haveTextMonth = FALSE;	int			is2digits = FALSE;	int			bc = FALSE;	/***	 * We'll insist on at least all of the date fields, but initialize the	 * remaining fields in case they are not set later...	 ***/	*dtype = DTK_DATE;	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:				/***				 * Integral julian day with attached time zone?				 * All other forms with JD will be separated into				 * distinct fields, so we handle just this case here.				 ***/				if (ptype == DTK_JULIAN)				{					char	   *cp;					int			val;					if (tzp == NULL)						return -1;					val = strtol(field[i], &cp, 10);					if (*cp != '-')						return -1;					j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);					/* Get the time zone from the end of the string */

⌨️ 快捷键说明

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