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

📄 datetime.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Used for SET australian_timezones to override North American ones */static datetkn australian_datetktbl[] = {	{"acst", TZ, POS(38)},		/* Cent. Australia */	{"cst", TZ, POS(42)},		/* Australia Central Std Time */	{"east", TZ, POS(40)},		/* East Australian Std Time */	{"est", TZ, POS(40)},		/* Australia Eastern Std Time */	{"sat", TZ, POS(38)},};static unsigned int australian_szdatetktbl = sizeof australian_datetktbl /sizeof australian_datetktbl[0];static datetkn deltatktbl[] = {	/* text, token, lexval */	{"@", IGNORE_DTF, 0},		/* postgres relative prefix */	{DAGO, AGO, 0},				/* "ago" indicates negative time offset */	{"c", UNITS, DTK_CENTURY},	/* "century" relative */	{"cent", UNITS, DTK_CENTURY},		/* "century" relative */	{"centuries", UNITS, DTK_CENTURY},	/* "centuries" relative */	{DCENTURY, UNITS, DTK_CENTURY},		/* "century" relative */	{"d", UNITS, DTK_DAY},		/* "day" relative */	{DDAY, UNITS, DTK_DAY},		/* "day" relative */	{"days", UNITS, DTK_DAY},	/* "days" relative */	{"dec", UNITS, DTK_DECADE}, /* "decade" relative */	{DDECADE, UNITS, DTK_DECADE},		/* "decade" relative */	{"decades", UNITS, DTK_DECADE},		/* "decades" relative */	{"decs", UNITS, DTK_DECADE},	/* "decades" relative */	{"h", UNITS, DTK_HOUR},		/* "hour" relative */	{DHOUR, UNITS, DTK_HOUR},	/* "hour" relative */	{"hours", UNITS, DTK_HOUR}, /* "hours" relative */	{"hr", UNITS, DTK_HOUR},	/* "hour" relative */	{"hrs", UNITS, DTK_HOUR},	/* "hours" relative */	{INVALID, RESERV, DTK_INVALID},		/* reserved for invalid time */	{"m", UNITS, DTK_MINUTE},	/* "minute" relative */	{"microsecon", UNITS, DTK_MICROSEC},		/* "microsecond" relative */	{"mil", UNITS, DTK_MILLENNIUM},		/* "millennium" relative */	{"millennia", UNITS, DTK_MILLENNIUM},		/* "millennia" relative */	{DMILLENNIUM, UNITS, DTK_MILLENNIUM},		/* "millennium" relative */	{"millisecon", UNITS, DTK_MILLISEC},		/* relative */	{"mils", UNITS, DTK_MILLENNIUM},	/* "millennia" relative */	{"min", UNITS, DTK_MINUTE}, /* "minute" relative */	{"mins", UNITS, DTK_MINUTE},	/* "minutes" relative */	{DMINUTE, UNITS, DTK_MINUTE},		/* "minute" relative */	{"minutes", UNITS, DTK_MINUTE},		/* "minutes" relative */	{"mon", UNITS, DTK_MONTH},	/* "months" relative */	{"mons", UNITS, DTK_MONTH}, /* "months" relative */	{DMONTH, UNITS, DTK_MONTH}, /* "month" relative */	{"months", UNITS, DTK_MONTH},	{"ms", UNITS, DTK_MILLISEC},	{"msec", UNITS, DTK_MILLISEC},	{DMILLISEC, UNITS, DTK_MILLISEC},	{"mseconds", UNITS, DTK_MILLISEC},	{"msecs", UNITS, DTK_MILLISEC},	{"qtr", UNITS, DTK_QUARTER},	/* "quarter" relative */	{DQUARTER, UNITS, DTK_QUARTER},		/* "quarter" relative */	{"reltime", IGNORE_DTF, 0}, /* pre-v6.1 "Undefined Reltime" */	{"s", UNITS, DTK_SECOND},	{"sec", UNITS, DTK_SECOND},	{DSECOND, UNITS, DTK_SECOND},	{"seconds", UNITS, DTK_SECOND},	{"secs", UNITS, DTK_SECOND},	{DTIMEZONE, UNITS, DTK_TZ}, /* "timezone" time offset */	{"timezone_h", UNITS, DTK_TZ_HOUR}, /* timezone hour units */	{"timezone_m", UNITS, DTK_TZ_MINUTE},		/* timezone minutes units */	{"undefined", RESERV, DTK_INVALID}, /* pre-v6.1 invalid time */	{"us", UNITS, DTK_MICROSEC},	/* "microsecond" relative */	{"usec", UNITS, DTK_MICROSEC},		/* "microsecond" relative */	{DMICROSEC, UNITS, DTK_MICROSEC},	/* "microsecond" relative */	{"useconds", UNITS, DTK_MICROSEC},	/* "microseconds" relative */	{"usecs", UNITS, DTK_MICROSEC},		/* "microseconds" relative */	{"w", UNITS, DTK_WEEK},		/* "week" relative */	{DWEEK, UNITS, DTK_WEEK},	/* "week" relative */	{"weeks", UNITS, DTK_WEEK}, /* "weeks" relative */	{"y", UNITS, DTK_YEAR},		/* "year" relative */	{DYEAR, UNITS, DTK_YEAR},	/* "year" relative */	{"years", UNITS, DTK_YEAR}, /* "years" relative */	{"yr", UNITS, DTK_YEAR},	/* "year" relative */	{"yrs", UNITS, DTK_YEAR},	/* "years" relative */};static unsigned int szdeltatktbl = sizeof deltatktbl / sizeof deltatktbl[0];static datetkn *datecache[MAXDATEFIELDS] = {NULL};static datetkn *deltacache[MAXDATEFIELDS] = {NULL};/* * Calendar time to Julian date conversions. * Julian date is commonly used in astronomical applications, *	since it is numerically accurate and computationally simple. * The algorithms here will accurately convert between Julian day *	and calendar date for all non-negative Julian days *	(i.e. from Nov 24, -4713 on). * * These routines will be used by other date/time packages * - thomas 97/02/25 * * Rewritten to eliminate overflow problems. This now allows the * routines to work correctly for all Julian day counts from * 0 to 2147483647	(Nov 24, -4713 to Jun 3, 5874898) assuming * a 32-bit integer. Longer types should also work to the limits * of their precision. */intdate2j(int y, int m, int d){	int			julian;	int			century;	if (m > 2)	{		m += 1;		y += 4800;	}	else	{		m += 13;		y += 4799;	}	century = y / 100;	julian = y * 365 - 32167;	julian += y / 4 - century + century / 4;	julian += 7834 * m / 256 + d;	return julian;}	/* date2j() */voidj2date(int jd, int *year, int *month, int *day){	unsigned int julian;	unsigned int quad;	unsigned int extra;	int			y;	julian = jd;	julian += 32044;	quad = julian / 146097;	extra = (julian - quad * 146097) * 4 + 3;	julian += 60 + quad * 3 + extra / 146097;	quad = julian / 1461;	julian -= quad * 1461;	y = julian * 4 / 1461;	julian = ((y != 0) ? ((julian + 305) % 365) : ((julian + 306) % 366))		+ 123;	y += quad * 4;	*year = y - 4800;	quad = julian * 2141 / 65536;	*day = julian - 7834 * quad / 256;	*month = (quad + 10) % 12 + 1;	return;}	/* j2date() *//* * j2day - convert Julian date to day-of-week (0..6 == Sun..Sat) * * Note: various places use the locution j2day(date - 1) to produce a * result according to the convention 0..6 = Mon..Sun.	This is a bit of * a crock, but will work as long as the computation here is just a modulo. */intj2day(int date){	unsigned int day;	day = date;	day += 1;	day %= 7;	return (int) day;}	/* j2day() *//* * GetCurrentDateTime() * * Get the transaction start time ("now()") broken down as a struct pg_tm. */voidGetCurrentDateTime(struct pg_tm * tm){	int			tz;	fsec_t		fsec;	timestamp2tm(GetCurrentTransactionStartTimestamp(), &tz, tm, &fsec,				 NULL, NULL);	/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */}/* * GetCurrentTimeUsec() * * Get the transaction start time ("now()") broken down as a struct pg_tm, * including fractional seconds and timezone offset. */voidGetCurrentTimeUsec(struct pg_tm * tm, fsec_t *fsec, int *tzp){	int			tz;	timestamp2tm(GetCurrentTransactionStartTimestamp(), &tz, tm, fsec,				 NULL, NULL);	/* Note: don't pass NULL tzp to timestamp2tm; affects behavior */	if (tzp != NULL)		*tzp = tz;}/* TrimTrailingZeros() * ... resulting from printing numbers with full precision. */static voidTrimTrailingZeros(char *str){	int			len = strlen(str);#if 0	/* chop off trailing one to cope with interval rounding */	if (strcmp(str + len - 4, "0001") == 0)	{		len -= 4;		*(str + len) = '\0';	}#endif	/* chop off trailing zeros... but leave at least 2 fractional digits */	while (*(str + len - 1) == '0' && *(str + len - 3) != '.')	{		len--;		*(str + len) = '\0';	}}/* ParseDateTime() *	Break string into tokens based on a date/time context. *	Returns 0 if successful, DTERR code if bogus input detected. * * timestr - the input string * workbuf - workspace for field string storage. This must be *	 larger than the largest legal input for this datetime type -- *	 some additional space will be needed to NUL terminate fields. * buflen - the size of workbuf * field[] - pointers to field strings are returned in this array * ftype[] - field type indicators are returned in this array * maxfields - dimensions of the above two arrays * *numfields - set to the actual number of fields detected * * The fields extracted from the input are stored as separate, * null-terminated strings in the workspace at workbuf. Any text is * converted to lower case. * * 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(const char *timestr, char *workbuf, size_t buflen,			  char **field, int *ftype, int maxfields, int *numfields){	int			nf = 0;	const char *cp = timestr;	char	   *bufp = workbuf;	const char *bufend = workbuf + buflen;	/*	 * Set the character pointed-to by "bufptr" to "newchar", and increment	 * "bufptr". "end" gives the end of the buffer -- we return an error if	 * there is no space left to append a character to the buffer. Note that	 * "bufptr" is evaluated twice.	 */#define APPEND_CHAR(bufptr, end, newchar)		\	do											\	{											\		if (((bufptr) + 1) >= (end))			\			return DTERR_BAD_FORMAT;			\		*(bufptr)++ = newchar;					\	} while (0)	/* outer loop through fields */	while (*cp != '\0')	{		/* Ignore spaces between fields */		if (isspace((unsigned char) *cp))		{			cp++;			continue;		}		/* Record start of current field */		if (nf >= maxfields)			return DTERR_BAD_FORMAT;		field[nf] = bufp;		/* leading digit? then date or time */		if (isdigit((unsigned char) *cp))		{			APPEND_CHAR(bufp, bufend, *cp++);			while (isdigit((unsigned char) *cp))				APPEND_CHAR(bufp, bufend, *cp++);			/* time field? */			if (*cp == ':')			{				ftype[nf] = DTK_TIME;				APPEND_CHAR(bufp, bufend, *cp++);				while (isdigit((unsigned char) *cp) ||					   (*cp == ':') || (*cp == '.'))					APPEND_CHAR(bufp, bufend, *cp++);			}			/* date field? allow embedded text month */			else if (*cp == '-' || *cp == '/' || *cp == '.')			{				/* save delimiting character to use later */				char		delim = *cp;				APPEND_CHAR(bufp, bufend, *cp++);				/* second field is all digits? then no embedded text month */				if (isdigit((unsigned char) *cp))				{					ftype[nf] = ((delim == '.') ? DTK_NUMBER : DTK_DATE);					while (isdigit((unsigned char) *cp))						APPEND_CHAR(bufp, bufend, *cp++);					/*					 * insist that the delimiters match to get a three-field					 * date.					 */					if (*cp == delim)					{						ftype[nf] = DTK_DATE;						APPEND_CHAR(bufp, bufend, *cp++);						while (isdigit((unsigned char) *cp) || *cp == delim)							APPEND_CHAR(bufp, bufend, *cp++);					}				}				else				{					ftype[nf] = DTK_DATE;					while (isalnum((unsigned char) *cp) || *cp == delim)						APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));				}			}			/*			 * 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 (*cp == '.')		{			APPEND_CHAR(bufp, bufend, *cp++);			while (isdigit((unsigned char) *cp))				APPEND_CHAR(bufp, bufend, *cp++);			ftype[nf] = DTK_NUMBER;		}		/*		 * text? then date string, month, day of week, special, or timezone		 */		else if (isalpha((unsigned char) *cp))		{			ftype[nf] = DTK_STRING;			APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));			while (isalpha((unsigned char) *cp))				APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));			/*			 * Full date string with leading text month? Could also be a POSIX			 * time zone...			 */			if (*cp == '-' || *cp == '/' || *cp == '.')			{				char		delim = *cp;				ftype[nf] = DTK_DATE;				APPEND_CHAR(bufp, bufend, *cp++);				while (isdigit((unsigned char) *cp) || *cp == delim)					APPEND_CHAR(bufp, bufend, *cp++);			}		}		/* sign? then special or numeric timezone */		else if (*cp == '+' || *cp == '-')		{			APPEND_CHAR(bufp, bufend, *cp++);			/* soak up leading whitespace */			while (isspace((unsigned char) *cp))				cp++;			/* numeric timezone? */			if (isdigit((unsigned char) *cp))			{				ftype[nf] = DTK_TZ;				APPEND_CHAR(bufp, bufend, *cp++);				while (isdigit((unsigned char) *cp) ||					   *cp == ':' || *cp == '.')					APPEND_CHAR(bufp, bufend, *cp++);			}			/* special? */			else if (isalpha((unsigned char) *cp))			{				ftype[nf] = DTK_SPECIAL;				APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));				while (isalpha((unsigned char) *cp))					APPEND_CHAR(bufp, bufend, pg_tolower((unsigned char) *cp++));			}			/* otherwise something wrong... */			else				return DTERR_BAD_FORMAT;		}		/* ignore other punctuation but use as delimiter */		else if (ispunct((unsigned char) *cp))		{			cp++;			continue;		}		/* otherwise, something is not right... */		else			return DTERR_BAD_FORMAT;		/* force in a delimiter after each field */		*bufp++ = '\0';		nf++;	}	*numfields = nf;	return 0;}/* DecodeDateTime() * Interpret previously parsed fields for general date and time. * Return 0 if full date, 1 if only time, and negative DTERR code if problems. * (Currently, all callers treat 1 as an error return too.) * *		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 pg_tm * tm, fsec_t *fsec, int *tzp){	int			fmask = 0,				tmask,				type;	int			ptype = 0;		/* "prefix type" for ISO y2001m02d04 format */	int			i;	int			val;	int			dterr;	int			mer = HR24;	bool		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;

⌨️ 快捷键说明

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