interval.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 831 行 · 第 1/2 页

C
831
字号
	if (*fsec != 0)	{		int			sec;#ifdef HAVE_INT64_TIMESTAMP		sec = (*fsec / INT64CONST(1000000));		*fsec -= (sec * INT64CONST(1000000));#else		TMODULO(*fsec, sec, 1e0);#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 is_nonzero when determining the signs of hour/minute/seconds	 * fields.	 */	switch (style)	{			/* compatible with ISO date formats */		case USE_ISO_DATES:			if (tm->tm_year != 0)			{				sprintf(cp, "%d year%s",						tm->tm_year, ((tm->tm_year != 1) ? "s" : ""));				cp += strlen(cp);				is_before = (tm->tm_year < 0);				is_nonzero = TRUE;			}			if (tm->tm_mon != 0)			{				sprintf(cp, "%s%s%d mon%s", (is_nonzero ? " " : ""),						((is_before && (tm->tm_mon > 0)) ? "+" : ""),						tm->tm_mon, ((tm->tm_mon != 1) ? "s" : ""));				cp += strlen(cp);				is_before = (tm->tm_mon < 0);				is_nonzero = TRUE;			}			if (tm->tm_mday != 0)			{				sprintf(cp, "%s%s%d day%s", (is_nonzero ? " " : ""),						((is_before && (tm->tm_mday > 0)) ? "+" : ""),						tm->tm_mday, ((tm->tm_mday != 1) ? "s" : ""));				cp += strlen(cp);				is_before = (tm->tm_mday < 0);				is_nonzero = TRUE;			}			if ((!is_nonzero) || (tm->tm_hour != 0) || (tm->tm_min != 0)				|| (tm->tm_sec != 0) || (fsec != 0))			{				int			minus = ((tm->tm_hour < 0) || (tm->tm_min < 0)									 || (tm->tm_sec < 0) || (fsec < 0));				sprintf(cp, "%s%s%02d:%02d", (is_nonzero ? " " : ""),						(minus ? "-" : (is_before ? "+" : "")),						abs(tm->tm_hour), abs(tm->tm_min));				cp += strlen(cp);				/* Mark as "non-zero" since the fields are now filled in */				is_nonzero = TRUE;				/* fractional seconds? */				if (fsec != 0)				{#ifdef HAVE_INT64_TIMESTAMP					sprintf(cp, ":%02d", abs(tm->tm_sec));					cp += strlen(cp);					sprintf(cp, ".%06d", ((fsec >= 0) ? fsec : -(fsec)));#else					fsec += tm->tm_sec;					sprintf(cp, ":%013.10f", fabs(fsec));#endif					TrimTrailingZeros(cp);					cp += strlen(cp);					is_nonzero = TRUE;				}				/* otherwise, integer seconds only? */				else if (tm->tm_sec != 0)				{					sprintf(cp, ":%02d", abs(tm->tm_sec));					cp += strlen(cp);					is_nonzero = TRUE;				}			}			break;		case USE_POSTGRES_DATES:		default:			strcpy(cp, "@ ");			cp += strlen(cp);			if (tm->tm_year != 0)			{				int			year = tm->tm_year;				if (tm->tm_year < 0)					year = -year;				sprintf(cp, "%d year%s", year,						((year != 1) ? "s" : ""));				cp += strlen(cp);				is_before = (tm->tm_year < 0);				is_nonzero = TRUE;			}			if (tm->tm_mon != 0)			{				int			mon = tm->tm_mon;				if (is_before || ((!is_nonzero) && (tm->tm_mon < 0)))					mon = -mon;				sprintf(cp, "%s%d mon%s", (is_nonzero ? " " : ""), mon,						((mon != 1) ? "s" : ""));				cp += strlen(cp);				if (!is_nonzero)					is_before = (tm->tm_mon < 0);				is_nonzero = TRUE;			}			if (tm->tm_mday != 0)			{				int			day = tm->tm_mday;				if (is_before || ((!is_nonzero) && (tm->tm_mday < 0)))					day = -day;				sprintf(cp, "%s%d day%s", (is_nonzero ? " " : ""), day,						((day != 1) ? "s" : ""));				cp += strlen(cp);				if (!is_nonzero)					is_before = (tm->tm_mday < 0);				is_nonzero = TRUE;			}			if (tm->tm_hour != 0)			{				int			hour = tm->tm_hour;				if (is_before || ((!is_nonzero) && (tm->tm_hour < 0)))					hour = -hour;				sprintf(cp, "%s%d hour%s", (is_nonzero ? " " : ""), hour,						((hour != 1) ? "s" : ""));				cp += strlen(cp);				if (!is_nonzero)					is_before = (tm->tm_hour < 0);				is_nonzero = TRUE;			}			if (tm->tm_min != 0)			{				int			min = tm->tm_min;				if (is_before || ((!is_nonzero) && (tm->tm_min < 0)))					min = -min;				sprintf(cp, "%s%d min%s", (is_nonzero ? " " : ""), min,						((min != 1) ? "s" : ""));				cp += strlen(cp);				if (!is_nonzero)					is_before = (tm->tm_min < 0);				is_nonzero = TRUE;			}			/* fractional seconds? */			if (fsec != 0)			{#ifdef HAVE_INT64_TIMESTAMP				if (is_before || ((!is_nonzero) && (tm->tm_sec < 0)))					tm->tm_sec = -tm->tm_sec;				sprintf(cp, "%s%d.%02d secs", (is_nonzero ? " " : ""),						tm->tm_sec, (((int) fsec) / 10000));				cp += strlen(cp);				if (!is_nonzero)					is_before = (fsec < 0);#else				fsec_t		sec;				fsec += tm->tm_sec;				sec = fsec;				if (is_before || ((!is_nonzero) && (fsec < 0)))					sec = -sec;				sprintf(cp, "%s%.2f secs", (is_nonzero ? " " : ""), sec);				cp += strlen(cp);				if (!is_nonzero)					is_before = (fsec < 0);#endif				is_nonzero = TRUE;				/* otherwise, integer seconds only? */			}			else if (tm->tm_sec != 0)			{				int			sec = tm->tm_sec;				if (is_before || ((!is_nonzero) && (tm->tm_sec < 0)))					sec = -sec;				sprintf(cp, "%s%d sec%s", (is_nonzero ? " " : ""), sec,						((sec != 1) ? "s" : ""));				cp += strlen(cp);				if (!is_nonzero)					is_before = (tm->tm_sec < 0);				is_nonzero = TRUE;			}			break;	}	/* identically zero? then put in a unitless zero... */	if (!is_nonzero)	{		strcat(cp, "0");		cp += strlen(cp);	}	if (is_before && (style == USE_POSTGRES_DATES))	{		strcat(cp, " ago");		cp += strlen(cp);	}	return 0;}	/* EncodeInterval() *//* interval2tm() * Convert a interval data type to a tm structure. */static intinterval2tm(interval span, struct tm * tm, fsec_t *fsec){#ifdef HAVE_INT64_TIMESTAMP	int64		time;#else	double		time;#endif	if (span.month != 0)	{		tm->tm_year = span.month / 12;		tm->tm_mon = span.month % 12;	}	else	{		tm->tm_year = 0;		tm->tm_mon = 0;	}	time = span.time;#ifdef HAVE_INT64_TIMESTAMP	tm->tm_mday = (time / INT64CONST(86400000000));	time -= (tm->tm_mday * INT64CONST(86400000000));	tm->tm_hour = (time / INT64CONST(3600000000));	time -= (tm->tm_hour * INT64CONST(3600000000));	tm->tm_min = (time / INT64CONST(60000000));	time -= (tm->tm_min * INT64CONST(60000000));	tm->tm_sec = (time / INT64CONST(1000000));	*fsec = (time - (tm->tm_sec * INT64CONST(1000000)));#else	TMODULO(time, tm->tm_mday, 86400e0);	TMODULO(time, tm->tm_hour, 3600e0);	TMODULO(time, tm->tm_min, 60e0);	TMODULO(time, tm->tm_sec, 1e0);	*fsec = time;#endif	return 0;}	/* interval2tm() */static inttm2interval(struct tm * tm, fsec_t fsec, interval *span){	span->month = ((tm->tm_year * 12) + tm->tm_mon);#ifdef HAVE_INT64_TIMESTAMP	span->time = ((((((((tm->tm_mday * INT64CONST(24))						+ tm->tm_hour) * INT64CONST(60))					  + tm->tm_min) * INT64CONST(60))					+ tm->tm_sec) * INT64CONST(1000000)) + fsec);#else	span->time = ((((((tm->tm_mday * 24.0)					  + tm->tm_hour) * 60.0)					+ tm->tm_min) * 60.0)				  + tm->tm_sec);	span->time = JROUND(span->time + fsec);#endif	return 0;}	/* tm2interval() */interval *PGTYPESinterval_from_asc(char *str, char **endptr){	interval   *result = NULL;	fsec_t		fsec;	struct tm	tt,			   *tm = &tt;	int			dtype;	int			nf;	char	   *field[MAXDATEFIELDS];	int			ftype[MAXDATEFIELDS];	char		lowstr[MAXDATELEN + MAXDATEFIELDS];	char	   *realptr;	char	  **ptr = (endptr != NULL) ? endptr : &realptr;	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;	if (strlen(str) >= sizeof(lowstr))	{		errno = PGTYPES_INTVL_BAD_INTERVAL;		return NULL;	}	if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf, ptr) != 0)		|| (DecodeInterval(field, ftype, nf, &dtype, tm, &fsec) != 0))	{		errno = PGTYPES_INTVL_BAD_INTERVAL;		return NULL;	}	result = (interval *) pgtypes_alloc(sizeof(interval));	if (!result)		return NULL;	if (dtype != DTK_DELTA)	{		errno = PGTYPES_INTVL_BAD_INTERVAL;		free(result);		return NULL;	}	if (tm2interval(tm, fsec, result) != 0)	{		errno = PGTYPES_INTVL_BAD_INTERVAL;		free(result);		return NULL;	}	return result;}char *PGTYPESinterval_to_asc(interval *span){	struct tm	tt,			   *tm = &tt;	fsec_t		fsec;	char		buf[MAXDATELEN + 1];	int			DateStyle = 0;	if (interval2tm(*span, tm, &fsec) != 0)	{		errno = PGTYPES_INTVL_BAD_INTERVAL;		return NULL;	}	if (EncodeInterval(tm, fsec, DateStyle, buf) != 0)	{		errno = PGTYPES_INTVL_BAD_INTERVAL;		return NULL;	}	return pgtypes_strdup(buf);}intPGTYPESinterval_copy(interval *intvlsrc, interval *intrcldest){	intrcldest->time = intvlsrc->time;	intrcldest->month = intvlsrc->month;	return 0;}

⌨️ 快捷键说明

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