mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	timestamptz_trunc() should only recalculate the timezone when truncating
to DAY precision or coarser; leave the timezone alone when precision is HOUR or less. This avoids surprises for inputs near a DST transition time, as per example from Matthew Gabeler-Lee. (The only reason we recalculate at all is so that outputs that are supposed to represent days will come out as local midnight, and that's not relevant for sub-day precision.)
This commit is contained in:
		
							parent
							
								
									5ba04cd9f1
								
							
						
					
					
						commit
						c4acbb843b
					
				| @ -8,7 +8,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.113 2004/08/30 02:54:39 momjian Exp $ | ||||
|  *	  $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.114 2004/11/01 22:00:30 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -2842,6 +2842,7 @@ timestamptz_trunc(PG_FUNCTION_ARGS) | ||||
| 	int			tz; | ||||
| 	int			type, | ||||
| 				val; | ||||
| 	bool		redotz = false; | ||||
| 	char	   *lowunits; | ||||
| 	fsec_t		fsec; | ||||
| 	char	   *tzn; | ||||
| @ -2872,6 +2873,7 @@ timestamptz_trunc(PG_FUNCTION_ARGS) | ||||
| 				tm->tm_min = 0; | ||||
| 				tm->tm_sec = 0; | ||||
| 				fsec = 0; | ||||
| 				redotz = true; | ||||
| 				break; | ||||
| 				/* one may consider DTK_THOUSAND and DTK_HUNDRED... */ | ||||
| 			case DTK_MILLENNIUM: | ||||
| @ -2885,12 +2887,14 @@ timestamptz_trunc(PG_FUNCTION_ARGS) | ||||
| 					tm->tm_year = ((tm->tm_year + 999) / 1000) * 1000 - 999; | ||||
| 				else | ||||
| 					tm->tm_year = -((999 - (tm->tm_year - 1)) / 1000) * 1000 + 1; | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_CENTURY: | ||||
| 				/* truncating to the century? as above: -100, 1, 101... */ | ||||
| 				if (tm->tm_year > 0) | ||||
| 					tm->tm_year = ((tm->tm_year + 99) / 100) * 100 - 99; | ||||
| 				else | ||||
| 					tm->tm_year = -((99 - (tm->tm_year - 1)) / 100) * 100 + 1; | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_DECADE: | ||||
| 
 | ||||
| 				/*
 | ||||
| @ -2904,18 +2908,26 @@ timestamptz_trunc(PG_FUNCTION_ARGS) | ||||
| 					else | ||||
| 						tm->tm_year = -((8 - (tm->tm_year - 1)) / 10) * 10; | ||||
| 				} | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_YEAR: | ||||
| 				tm->tm_mon = 1; | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_QUARTER: | ||||
| 				tm->tm_mon = (3 * ((tm->tm_mon - 1) / 3)) + 1; | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_MONTH: | ||||
| 				tm->tm_mday = 1; | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_DAY: | ||||
| 				tm->tm_hour = 0; | ||||
| 				redotz = true;	/* for all cases >= DAY */ | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_HOUR: | ||||
| 				tm->tm_min = 0; | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_MINUTE: | ||||
| 				tm->tm_sec = 0; | ||||
| 				/* FALL THRU */ | ||||
| 			case DTK_SECOND: | ||||
| 				fsec = 0; | ||||
| 				break; | ||||
| @ -2941,7 +2953,8 @@ timestamptz_trunc(PG_FUNCTION_ARGS) | ||||
| 				result = 0; | ||||
| 		} | ||||
| 
 | ||||
| 		tz = DetermineLocalTimeZone(tm); | ||||
| 		if (redotz) | ||||
| 			tz = DetermineLocalTimeZone(tm); | ||||
| 
 | ||||
| 		if (tm2timestamp(tm, fsec, &tz, &result) != 0) | ||||
| 			ereport(ERROR, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user