date.c

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

C
2,274
字号
	result->time = (time->time + span->time);	result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000));	if (result->time < INT64CONST(0))		result->time += INT64CONST(86400000000);#else	result->time = (time->time + span->time);	TMODULO(result->time, time1.time, 86400e0);	if (result->time < 0)		result->time += 86400;#endif	result->zone = time->zone;	PG_RETURN_TIMETZADT_P(result);}/* timetz_mi_interval() * Subtract interval from timetz. */Datumtimetz_mi_interval(PG_FUNCTION_ARGS){	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(0);	Interval   *span = PG_GETARG_INTERVAL_P(1);	TimeTzADT  *result;#ifndef HAVE_INT64_TIMESTAMP	TimeTzADT	time1;#endif	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP	result->time = (time->time - span->time);	result->time -= (result->time / INT64CONST(86400000000) * INT64CONST(86400000000));	if (result->time < INT64CONST(0))		result->time += INT64CONST(86400000000);#else	result->time = (time->time - span->time);	TMODULO(result->time, time1.time, 86400e0);	if (result->time < 0)		result->time += 86400;#endif	result->zone = time->zone;	PG_RETURN_TIMETZADT_P(result);}/* overlaps_timetz() --- implements the SQL92 OVERLAPS operator. * * Algorithm is per SQL92 spec.  This is much harder than you'd think * because the spec requires us to deliver a non-null answer in some cases * where some of the inputs are null. */Datumoverlaps_timetz(PG_FUNCTION_ARGS){	/*	 * The arguments are TimeTzADT *, but we leave them as generic Datums	 * for convenience of notation --- and to avoid dereferencing nulls.	 */	Datum		ts1 = PG_GETARG_DATUM(0);	Datum		te1 = PG_GETARG_DATUM(1);	Datum		ts2 = PG_GETARG_DATUM(2);	Datum		te2 = PG_GETARG_DATUM(3);	bool		ts1IsNull = PG_ARGISNULL(0);	bool		te1IsNull = PG_ARGISNULL(1);	bool		ts2IsNull = PG_ARGISNULL(2);	bool		te2IsNull = PG_ARGISNULL(3);#define TIMETZ_GT(t1,t2) \	DatumGetBool(DirectFunctionCall2(timetz_gt,t1,t2))#define TIMETZ_LT(t1,t2) \	DatumGetBool(DirectFunctionCall2(timetz_lt,t1,t2))	/*	 * If both endpoints of interval 1 are null, the result is null	 * (unknown). If just one endpoint is null, take ts1 as the non-null	 * one. Otherwise, take ts1 as the lesser endpoint.	 */	if (ts1IsNull)	{		if (te1IsNull)			PG_RETURN_NULL();		/* swap null for non-null */		ts1 = te1;		te1IsNull = true;	}	else if (!te1IsNull)	{		if (TIMETZ_GT(ts1, te1))		{			Datum		tt = ts1;			ts1 = te1;			te1 = tt;		}	}	/* Likewise for interval 2. */	if (ts2IsNull)	{		if (te2IsNull)			PG_RETURN_NULL();		/* swap null for non-null */		ts2 = te2;		te2IsNull = true;	}	else if (!te2IsNull)	{		if (TIMETZ_GT(ts2, te2))		{			Datum		tt = ts2;			ts2 = te2;			te2 = tt;		}	}	/*	 * At this point neither ts1 nor ts2 is null, so we can consider three	 * cases: ts1 > ts2, ts1 < ts2, ts1 = ts2	 */	if (TIMETZ_GT(ts1, ts2))	{		/*		 * This case is ts1 < te2 OR te1 < te2, which may look redundant		 * but in the presence of nulls it's not quite completely so.		 */		if (te2IsNull)			PG_RETURN_NULL();		if (TIMETZ_LT(ts1, te2))			PG_RETURN_BOOL(true);		if (te1IsNull)			PG_RETURN_NULL();		/*		 * If te1 is not null then we had ts1 <= te1 above, and we just		 * found ts1 >= te2, hence te1 >= te2.		 */		PG_RETURN_BOOL(false);	}	else if (TIMETZ_LT(ts1, ts2))	{		/* This case is ts2 < te1 OR te2 < te1 */		if (te1IsNull)			PG_RETURN_NULL();		if (TIMETZ_LT(ts2, te1))			PG_RETURN_BOOL(true);		if (te2IsNull)			PG_RETURN_NULL();		/*		 * If te2 is not null then we had ts2 <= te2 above, and we just		 * found ts2 >= te1, hence te2 >= te1.		 */		PG_RETURN_BOOL(false);	}	else	{		/*		 * For ts1 = ts2 the spec says te1 <> te2 OR te1 = te2, which is a		 * rather silly way of saying "true if both are nonnull, else		 * null".		 */		if (te1IsNull || te2IsNull)			PG_RETURN_NULL();		PG_RETURN_BOOL(true);	}#undef TIMETZ_GT#undef TIMETZ_LT}Datumtimetz_time(PG_FUNCTION_ARGS){	TimeTzADT  *timetz = PG_GETARG_TIMETZADT_P(0);	TimeADT		result;	/* swallow the time zone and just return the time */	result = timetz->time;	PG_RETURN_TIMEADT(result);}Datumtime_timetz(PG_FUNCTION_ARGS){	TimeADT		time = PG_GETARG_TIMEADT(0);	TimeTzADT  *result;	struct tm	tt,			   *tm = &tt;	fsec_t		fsec;	int			tz;	GetCurrentDateTime(tm);	time2tm(time, tm, &fsec);	tz = DetermineLocalTimeZone(tm);	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));	result->time = time;	result->zone = tz;	PG_RETURN_TIMETZADT_P(result);}/* timestamptz_timetz() * Convert timestamp to timetz data type. */Datumtimestamptz_timetz(PG_FUNCTION_ARGS){	TimestampTz timestamp = PG_GETARG_TIMESTAMP(0);	TimeTzADT  *result;	struct tm	tt,			   *tm = &tt;	int			tz;	fsec_t		fsec;	char	   *tzn;	if (TIMESTAMP_NOT_FINITE(timestamp))		PG_RETURN_NULL();	if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0)		ereport(ERROR,				(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),				 errmsg("timestamp out of range")));	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));	tm2timetz(tm, fsec, tz, result);	PG_RETURN_TIMETZADT_P(result);}/* datetimetz_timestamptz() * Convert date and timetz to timestamp with time zone data type. * Timestamp is stored in GMT, so add the time zone * stored with the timetz to the result. * - thomas 2000-03-10 */Datumdatetimetz_timestamptz(PG_FUNCTION_ARGS){	DateADT		date = PG_GETARG_DATEADT(0);	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);	TimestampTz result;#ifdef HAVE_INT64_TIMESTAMP	result = (((date * INT64CONST(86400000000)) + time->time)			  + (time->zone * INT64CONST(1000000)));#else	result = (((date * 86400.0) + time->time) + time->zone);#endif	PG_RETURN_TIMESTAMP(result);}/* timetz_text() * Convert timetz to text data type. */Datumtimetz_text(PG_FUNCTION_ARGS){	/* Input is a Timetz, but may as well leave it in Datum form */	Datum		timetz = PG_GETARG_DATUM(0);	text	   *result;	char	   *str;	int			len;	str = DatumGetCString(DirectFunctionCall1(timetz_out, timetz));	len = (strlen(str) + VARHDRSZ);	result = palloc(len);	VARATT_SIZEP(result) = len;	memmove(VARDATA(result), str, (len - VARHDRSZ));	pfree(str);	PG_RETURN_TEXT_P(result);}/* text_timetz() * Convert text string to timetz. * Text type is not null terminated, so use temporary string *	then call the standard input routine. */Datumtext_timetz(PG_FUNCTION_ARGS){	text	   *str = PG_GETARG_TEXT_P(0);	int			i;	char	   *sp,			   *dp,				dstr[MAXDATELEN + 1];	if (VARSIZE(str) - VARHDRSZ > MAXDATELEN)		ereport(ERROR,				(errcode(ERRCODE_INVALID_DATETIME_FORMAT),		   errmsg("invalid input syntax for type time with time zone: \"%s\"",				  VARDATA(str))));	sp = VARDATA(str);	dp = dstr;	for (i = 0; i < (VARSIZE(str) - VARHDRSZ); i++)		*dp++ = *sp++;	*dp = '\0';	return DirectFunctionCall3(timetz_in,							   CStringGetDatum(dstr),							   ObjectIdGetDatum(InvalidOid),							   Int32GetDatum(-1));}/* timetz_part() * Extract specified field from time type. */Datumtimetz_part(PG_FUNCTION_ARGS){	text	   *units = PG_GETARG_TEXT_P(0);	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);	float8		result;	int			type,				val;	int			i;	char	   *up,			   *lp,				lowunits[MAXDATELEN + 1];	if (VARSIZE(units) - VARHDRSZ > MAXDATELEN)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("\"time with time zone\" units \"%s\" not recognized",						DatumGetCString(DirectFunctionCall1(textout,											 PointerGetDatum(units))))));	up = VARDATA(units);	lp = lowunits;	for (i = 0; i < (VARSIZE(units) - VARHDRSZ); i++)		*lp++ = tolower((unsigned char) *up++);	*lp = '\0';	type = DecodeUnits(0, lowunits, &val);	if (type == UNKNOWN_FIELD)		type = DecodeSpecial(0, lowunits, &val);	if (type == UNITS)	{		double		dummy;		int			tz;		fsec_t		fsec;		struct tm	tt,				   *tm = &tt;		timetz2tm(time, tm, &fsec, &tz);		switch (val)		{			case DTK_TZ:				result = -tz;				break;			case DTK_TZ_MINUTE:				result = -tz;				result /= 60;				FMODULO(result, dummy, 60e0);				break;			case DTK_TZ_HOUR:				dummy = -tz;				FMODULO(dummy, result, 3600e0);				break;			case DTK_MICROSEC:#ifdef HAVE_INT64_TIMESTAMP				result = ((tm->tm_sec * INT64CONST(1000000)) + fsec);#else				result = ((tm->tm_sec + fsec) * 1000000);#endif				break;			case DTK_MILLISEC:#ifdef HAVE_INT64_TIMESTAMP				result = ((tm->tm_sec * INT64CONST(1000))						  + (fsec / INT64CONST(1000)));#else				result = ((tm->tm_sec + fsec) * 1000);#endif				break;			case DTK_SECOND:#ifdef HAVE_INT64_TIMESTAMP				result = (tm->tm_sec + (fsec / INT64CONST(1000000)));#else				result = (tm->tm_sec + fsec);#endif				break;			case DTK_MINUTE:				result = tm->tm_min;				break;			case DTK_HOUR:				result = tm->tm_hour;				break;			case DTK_DAY:			case DTK_MONTH:			case DTK_QUARTER:			case DTK_YEAR:			case DTK_DECADE:			case DTK_CENTURY:			case DTK_MILLENNIUM:			default:				ereport(ERROR,						(errcode(ERRCODE_INVALID_PARAMETER_VALUE),						 errmsg("\"time with time zone\" units \"%s\" not recognized",							 DatumGetCString(DirectFunctionCall1(textout,											 PointerGetDatum(units))))));				result = 0;		}	}	else if ((type == RESERV) && (val == DTK_EPOCH))	{#ifdef HAVE_INT64_TIMESTAMP		result = ((time->time / 1000000e0) - time->zone);#else		result = (time->time - time->zone);#endif	}	else	{		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("\"time with time zone\" units \"%s\" not recognized",						DatumGetCString(DirectFunctionCall1(textout,											 PointerGetDatum(units))))));		result = 0;	}	PG_RETURN_FLOAT8(result);}/* timetz_zone() * Encode time with time zone type with specified time zone. */Datumtimetz_zone(PG_FUNCTION_ARGS){	text	   *zone = PG_GETARG_TEXT_P(0);	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);	TimeTzADT  *result;	int			tz;	int			type,				val;	int			i;	char	   *up,			   *lp,				lowzone[MAXDATELEN + 1];	if (VARSIZE(zone) - VARHDRSZ > MAXDATELEN)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("time zone \"%s\" not recognized",						DatumGetCString(DirectFunctionCall1(textout,											  PointerGetDatum(zone))))));	up = VARDATA(zone);	lp = lowzone;	for (i = 0; i < (VARSIZE(zone) - VARHDRSZ); i++)		*lp++ = tolower((unsigned char) *up++);	*lp = '\0';	type = DecodeSpecial(0, lowzone, &val);	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));	if ((type == TZ) || (type == DTZ))	{		tz = val * 60;#ifdef HAVE_INT64_TIMESTAMP		result->time = time->time + ((time->zone - tz) * INT64CONST(1000000));		while (result->time < INT64CONST(0))			result->time += INT64CONST(86400000000);		while (result->time >= INT64CONST(86400000000))			result->time -= INT64CONST(86400000000);#else		result->time = time->time + (time->zone - tz);		while (result->time < 0)			result->time += 86400;		while (result->time >= 86400)			result->time -= 86400;#endif		result->zone = tz;	}	else	{		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("time zone \"%s\" not recognized", lowzone)));		PG_RETURN_NULL();	}	PG_RETURN_TIMETZADT_P(result);}	/* timetz_zone() *//* timetz_izone() * Encode time with time zone type with specified time interval as time zone. */Datumtimetz_izone(PG_FUNCTION_ARGS){	Interval   *zone = PG_GETARG_INTERVAL_P(0);	TimeTzADT  *time = PG_GETARG_TIMETZADT_P(1);	TimeTzADT  *result;	int			tz;	if (zone->month != 0)		ereport(ERROR,				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),				 errmsg("\"interval\" time zone \"%s\" not valid",						DatumGetCString(DirectFunctionCall1(interval_out,											  PointerGetDatum(zone))))));#ifdef HAVE_INT64_TIMESTAMP	tz = -(zone->time / INT64CONST(1000000));#else	tz = -(zone->time);#endif	result = (TimeTzADT *) palloc(sizeof(TimeTzADT));#ifdef HAVE_INT64_TIMESTAMP	result->time = time->time + ((time->zone - tz) * INT64CONST(1000000));	while (result->time < INT64CONST(0))		result->time += INT64CONST(86400000000);	while (result->time >= INT64CONST(86400000000))		result->time -= INT64CONST(86400000000);#else	result->time = time->time + (time->zone - tz);	while (result->time < 0)		result->time += 86400;	while (result->time >= 86400)		result->time -= 86400;#endif	result->zone = tz;	PG_RETURN_TIMETZADT_P(result);}	/* timetz_izone() */

⌨️ 快捷键说明

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