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

📄 timestamp.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	pq_begintypsend(&buf);#ifdef HAVE_INT64_TIMESTAMP	pq_sendint64(&buf, interval->time);#else	pq_sendfloat8(&buf, interval->time);#endif	pq_sendint(&buf, interval->month, sizeof(interval->month));	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* interval_scale() * Adjust interval type for specified fields. * Used by PostgreSQL type system to stuff columns. */Datuminterval_scale(PG_FUNCTION_ARGS){	Interval   *interval = PG_GETARG_INTERVAL_P(0);	int32		typmod = PG_GETARG_INT32(1);	Interval   *result;	result = palloc(sizeof(Interval));	*result = *interval;	AdjustIntervalForTypmod(result, typmod);	PG_RETURN_INTERVAL_P(result);}static voidAdjustIntervalForTypmod(Interval *interval, int32 typmod){#ifdef HAVE_INT64_TIMESTAMP	static const int64 IntervalScales[MAX_INTERVAL_PRECISION + 1] = {		INT64CONST(1000000),		INT64CONST(100000),		INT64CONST(10000),		INT64CONST(1000),		INT64CONST(100),		INT64CONST(10),		INT64CONST(1)	};	static const int64 IntervalOffsets[MAX_INTERVAL_PRECISION + 1] = {		INT64CONST(500000),		INT64CONST(50000),		INT64CONST(5000),		INT64CONST(500),		INT64CONST(50),		INT64CONST(5),		INT64CONST(0)	};#else	static const double IntervalScales[MAX_INTERVAL_PRECISION + 1] = {		1,		10,		100,		1000,		10000,		100000,		1000000	};#endif	/*	 * Unspecified range and precision? Then not necessary to adjust.	 * Setting typmod to -1 is the convention for all types.	 */	if (typmod != -1)	{		int			range = INTERVAL_RANGE(typmod);		int			precision = INTERVAL_PRECISION(typmod);		if (range == INTERVAL_FULL_RANGE)		{			/* Do nothing... */		}		else if (range == INTERVAL_MASK(YEAR))		{			interval->month = ((interval->month / 12) * 12);			interval->time = 0;		}		else if (range == INTERVAL_MASK(MONTH))		{			interval->month %= 12;			interval->time = 0;		}		/* YEAR TO MONTH */		else if (range == (INTERVAL_MASK(YEAR) | INTERVAL_MASK(MONTH)))			interval->time = 0;		else if (range == INTERVAL_MASK(DAY))		{			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			interval->time = (((int) (interval->time / INT64CONST(86400000000)))							  * INT64CONST(86400000000));#else			interval->time = (((int) (interval->time / 86400)) * 86400);#endif		}		else if (range == INTERVAL_MASK(HOUR))		{#ifdef HAVE_INT64_TIMESTAMP			int64		day;#else			double		day;#endif			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			day = (interval->time / INT64CONST(86400000000));			interval->time -= (day * INT64CONST(86400000000));			interval->time = ((interval->time / INT64CONST(3600000000))							  * INT64CONST(3600000000));#else			TMODULO(interval->time, day, 86400.0);			interval->time = (((int) (interval->time / 3600)) * 3600.0);#endif		}		else if (range == INTERVAL_MASK(MINUTE))		{#ifdef HAVE_INT64_TIMESTAMP			int64		hour;#else			double		hour;#endif			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			hour = (interval->time / INT64CONST(3600000000));			interval->time -= (hour * INT64CONST(3600000000));			interval->time = ((interval->time / INT64CONST(60000000))							  * INT64CONST(60000000));#else			TMODULO(interval->time, hour, 3600.0);			interval->time = (((int) (interval->time / 60)) * 60);#endif		}		else if (range == INTERVAL_MASK(SECOND))		{#ifdef HAVE_INT64_TIMESTAMP			int64		minute;#else			double		minute;#endif			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			minute = (interval->time / INT64CONST(60000000));			interval->time -= (minute * INT64CONST(60000000));#else			TMODULO(interval->time, minute, 60.0);/*			interval->time = (int)(interval->time); */#endif		}		/* DAY TO HOUR */		else if (range == (INTERVAL_MASK(DAY) |						   INTERVAL_MASK(HOUR)))		{			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			interval->time = ((interval->time / INT64CONST(3600000000))							  * INT64CONST(3600000000));#else			interval->time = (((int) (interval->time / 3600)) * 3600);#endif		}		/* DAY TO MINUTE */		else if (range == (INTERVAL_MASK(DAY) |						   INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE)))		{			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			interval->time = ((interval->time / INT64CONST(60000000))							  * INT64CONST(60000000));#else			interval->time = (((int) (interval->time / 60)) * 60);#endif		}		/* DAY TO SECOND */		else if (range == (INTERVAL_MASK(DAY) |						   INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE) |						   INTERVAL_MASK(SECOND)))			interval->month = 0;		/* HOUR TO MINUTE */		else if (range == (INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE)))		{#ifdef HAVE_INT64_TIMESTAMP			int64		day;#else			double		day;#endif			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			day = (interval->time / INT64CONST(86400000000));			interval->time -= (day * INT64CONST(86400000000));			interval->time = ((interval->time / INT64CONST(60000000))							  * INT64CONST(60000000));#else			TMODULO(interval->time, day, 86400.0);			interval->time = (((int) (interval->time / 60)) * 60);#endif		}		/* HOUR TO SECOND */		else if (range == (INTERVAL_MASK(HOUR) |						   INTERVAL_MASK(MINUTE) |						   INTERVAL_MASK(SECOND)))		{#ifdef HAVE_INT64_TIMESTAMP			int64		day;#else			double		day;#endif			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			day = (interval->time / INT64CONST(86400000000));			interval->time -= (day * INT64CONST(86400000000));#else			TMODULO(interval->time, day, 86400.0);#endif		}		/* MINUTE TO SECOND */		else if (range == (INTERVAL_MASK(MINUTE) |						   INTERVAL_MASK(SECOND)))		{#ifdef HAVE_INT64_TIMESTAMP			int64		hour;#else			double		hour;#endif			interval->month = 0;#ifdef HAVE_INT64_TIMESTAMP			hour = (interval->time / INT64CONST(3600000000));			interval->time -= (hour * INT64CONST(3600000000));#else			TMODULO(interval->time, hour, 3600.0);#endif		}		else			elog(ERROR, "unrecognized interval typmod: %d", typmod);		/* Need to adjust precision? If not, don't even try! */		if (precision != INTERVAL_FULL_PRECISION)		{			if ((precision < 0) || (precision > MAX_INTERVAL_PRECISION))				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				errmsg("interval(%d) precision must be between %d and %d",					   precision, 0, MAX_INTERVAL_PRECISION)));			/*			 * Note: this round-to-nearest code is not completely			 * consistent about rounding values that are exactly halfway			 * between integral values.  On most platforms, rint() will			 * implement round-to-nearest-even, but the integer code			 * always rounds up (away from zero).  Is it worth trying to			 * be consistent?			 */#ifdef HAVE_INT64_TIMESTAMP			if (interval->time >= INT64CONST(0))			{				interval->time = (((interval->time + IntervalOffsets[precision]) / IntervalScales[precision])								  * IntervalScales[precision]);			}			else			{				interval->time = -(((-interval->time + IntervalOffsets[precision]) / IntervalScales[precision])								   * IntervalScales[precision]);			}#else			interval->time = (rint(((double) interval->time) * IntervalScales[precision])							  / IntervalScales[precision]);#endif		}	}	return;}/* EncodeSpecialTimestamp() * Convert reserved timestamp data type to string. */static intEncodeSpecialTimestamp(Timestamp dt, char *str){	if (TIMESTAMP_IS_NOBEGIN(dt))		strcpy(str, EARLY);	else if (TIMESTAMP_IS_NOEND(dt))		strcpy(str, LATE);	else		return FALSE;	return TRUE;}	/* EncodeSpecialTimestamp() */Datumnow(PG_FUNCTION_ARGS){	TimestampTz result;	AbsoluteTime sec;	int			usec;	sec = GetCurrentTransactionStartTimeUsec(&usec);	result = AbsoluteTimeUsecToTimestampTz(sec, usec);	PG_RETURN_TIMESTAMPTZ(result);}voiddt2time(Timestamp 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 / INT64CONST(3600000000));	time -= ((*hour) * INT64CONST(3600000000));	*min = (time / INT64CONST(60000000));	time -= ((*min) * INT64CONST(60000000));	*sec = (time / INT64CONST(1000000));	*fsec = (time - (*sec * INT64CONST(1000000)));#else	*hour = (time / 3600);	time -= ((*hour) * 3600);	*min = (time / 60);	time -= ((*min) * 60);	*sec = time;	*fsec = JROUND(time - *sec);#endif	return;}	/* dt2time() *//* timestamp2tm() * Convert timestamp data type to POSIX time structure. * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * Returns: *	 0 on success *	-1 on out of range * * For dates within the system-supported time_t range, convert to the *	local time zone. If out of this range, leave as GMT. - tgl 97/05/27 */inttimestamp2tm(Timestamp dt, int *tzp, struct tm *tm, fsec_t *fsec, char **tzn){#ifdef HAVE_INT64_TIMESTAMP	int			date;	int64		time;#else	double		date;	double		time;#endif	time_t		utime;#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)	struct tm  *tx;#endif	/*	 * If HasCTZSet is true then we have a brute force time zone	 * specified. Go ahead and rotate to the local time zone since we will	 * later bypass any calls which adjust the tm fields.	 */	if (HasCTZSet && (tzp != NULL))	{#ifdef HAVE_INT64_TIMESTAMP		dt -= (CTimeZone * INT64CONST(1000000));#else		dt -= CTimeZone;#endif	}	time = dt;#ifdef HAVE_INT64_TIMESTAMP	TMODULO(time, date, INT64CONST(86400000000));	if (time < INT64CONST(0))	{		time += INT64CONST(86400000000);		date -= 1;	}#else	TMODULO(time, date, 86400e0);	if (time < 0)	{		time += 86400;		date -= 1;	}#endif	/* Julian day routine does not work for negative Julian days */	if (date < -POSTGRES_EPOCH_JDATE)		return -1;	/* add offset to go from J2000 back to standard Julian date */	date += POSTGRES_EPOCH_JDATE;	j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);	dt2time(time, &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);	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.		 */		if (HasCTZSet)		{			*tzp = CTimeZone;			tm->tm_isdst = 0;#if defined(HAVE_TM_ZONE)			tm->tm_gmtoff = CTimeZone;			tm->tm_zone = NULL;#endif			if (tzn != NULL)				*tzn = NULL;		}		/*		 * Does this fall within the capabilities of the localtime()		 * interface? Then use this to rotate to the local time zone.		 */		else if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))		{			/*			 * Convert to integer, avoiding platform-specific			 * roundoff-in-wrong-direction errors, and adjust to			 * Unix epoch.  Note we have to do this in one step			 * because the intermediate result before adjustment			 * won't necessarily fit in an int32.			 */#ifdef HAVE_INT64_TIMESTAMP			utime = (dt - *fsec) / INT64CONST(1000000) +				(POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400;#else			utime = rint(dt - *fsec +						 (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400);#endif#if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE)			tx = localtime(&utime);			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;#if NOT_USED/* XXX HACK * Argh! My Linux box puts in a 1 second offset for dates less than 1970 *	but only if the seconds field was non-zero. So, don't copy the seconds *	field and instead carry forward from the original - thomas 97/06/18 * Note that Linux uses the standard freeware zic package as do *	many other platforms so this may not be Linux/ix86-specific. * Still shows a problem on my up to date Linux box - thomas 2001-01-17 */			tm->tm_sec = tx->tm_sec;#endif			tm->tm_isdst = tx->tm_isdst;#if defined(HAVE_TM_ZONE)			tm->tm_gmtoff = tx->tm_gmtoff;			tm->tm_zone = tx->tm_zone;			*tzp = -(tm->tm_gmtoff);	/* tm_gmtoff is Sun/DEC-ism */			if (tzn != NULL)				*tzn = (char *) tm->tm_zone;#elif defined(HAVE_INT_TIMEZONE)			*tzp = ((tm->tm_isdst > 0) ? (TIMEZONE_GLOBAL - 3600) : TIMEZONE_GLOBAL);			if (tzn != NULL)				*tzn = tzname[(tm->tm_isdst > 0)];#endif#else							/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */			*tzp = 0;			/* Mark this as *no* time zone available */			tm->tm_isdst = -1;			if (tzn != NULL)				*tzn = NULL;#endif		}		else		{			*tzp = 0;			/* Mark this as *no* time zone available */			tm->tm_isdst = -1;			if (tzn != NULL)				*tzn = NULL;		}	}	else	{		tm->tm_isdst = -1;		if (tzn != NULL)			*tzn = NULL;	}	return 0;}/* tm2timestamp() * Convert a tm structure to a timestamp data type. * Note that year is _not_ 1900-based, but is an explicit full value. * Also, month is one-based, _not_ zero-based. * * Returns -1 on failure (value out of range). */inttm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result){#ifdef HAVE_INT64_TIMESTAMP	int			date;	int64		time;#else	double		date,				time;#endif	/* Julian day routines are not correct for negative Julian days */	if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday))		return -1;	date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE;	time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec);#ifdef HAVE_INT64_TIMESTAMP	*result = (date * INT64CONST(86400000000)) + time;	/* check for major overflow */	if ((*result - time) / INT64CONST(86400000000) != date)		return -1;	/* check for just-barely overflow (okay except time-of-day wraps) */	if ((*result < 0) ? (date >= 0) : (date < 0))		return -1;#else	*result = ((date * 86400) + time);#endif	if (tzp != NULL)		*result = dt2local(*result, -(*tzp));	return 0;

⌨️ 快捷键说明

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