diff options
Diffstat (limited to 'src/backend/utils/adt/timestamp.c')
-rw-r--r-- | src/backend/utils/adt/timestamp.c | 70 |
1 files changed, 57 insertions, 13 deletions
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index 13dba7cb5c6..7632e1b8961 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.171 2007/01/05 22:19:42 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.172 2007/02/16 03:39:45 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -3749,32 +3749,57 @@ interval_trunc(PG_FUNCTION_ARGS) PG_RETURN_INTERVAL_P(result); } -/* isoweek2date() - * Convert ISO week of year number to date. - * The year field must be specified with the ISO year! - * karel 2000/08/07 +/* isoweek2j() + * + * Return the Julian day which corresponds to the first day (Monday) of the given ISO 8601 year and week. + * Julian days are used to convert between ISO week dates and Gregorian dates. */ -void -isoweek2date(int woy, int *year, int *mon, int *mday) +int +isoweek2j(int year, int week) { int day0, - day4, - dayn; + day4; - if (!*year) + if (!year) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("cannot calculate week number without year information"))); /* fourth day of current year */ - day4 = date2j(*year, 1, 4); + day4 = date2j(year, 1, 4); /* day0 == offset to first day of week (Monday) */ day0 = j2day(day4 - 1); - dayn = ((woy - 1) * 7) + (day4 - day0); + return ((week - 1) * 7) + (day4 - day0); +} + +/* isoweek2date() + * Convert ISO week of year number to date. + * The year field must be specified with the ISO year! + * karel 2000/08/07 + */ +void +isoweek2date(int woy, int *year, int *mon, int *mday) +{ + j2date(isoweek2j(*year, woy), year, mon, mday); +} + +/* isoweekdate2date() + * + * Convert an ISO 8601 week date (ISO year, ISO week and day of week) into a Gregorian date. + * Populates year, mon, and mday with the correct Gregorian values. + * year must be passed in as the ISO year. + */ +void +isoweekdate2date(int isoweek, int isowday, int *year, int *mon, int *mday) +{ + int jday; + + jday = isoweek2j(*year, isoweek); + jday += isowday - 1; - j2date(dayn, year, mon, mday); + j2date(jday, year, mon, mday); } /* date2isoweek() @@ -3887,6 +3912,17 @@ date2isoyear(int year, int mon, int mday) } +/* date2isoyearday() + * + * Returns the ISO 8601 day-of-year, given a Gregorian year, month and day. + * Possible return values are 1 through 371 (364 in non-leap years). + */ +int +date2isoyearday(int year, int mon, int mday) +{ + return date2j(year, mon, mday) - isoweek2j(date2isoyear(year, mon, mday), 1) + 1; +} + /* timestamp_part() * Extract specified field from timestamp. */ @@ -4029,6 +4065,10 @@ timestamp_part(PG_FUNCTION_ARGS) #endif break; + case DTK_ISOYEAR: + result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday); + break; + case DTK_TZ: case DTK_TZ_MINUTE: case DTK_TZ_HOUR: @@ -4256,6 +4296,10 @@ timestamptz_part(PG_FUNCTION_ARGS) #endif break; + case DTK_ISOYEAR: + result = date2isoyear(tm->tm_year, tm->tm_mon, tm->tm_mday); + break; + default: ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |