|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.109 2005/05/26 02:04:13 neilc Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/utils/adt/date.c,v 1.110 2005/06/15 00:34:08 momjian Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
|
18 | 18 | #include <ctype.h>
|
19 | 19 | #include <limits.h>
|
20 | 20 | #include <float.h>
|
| 21 | +#include <time.h> |
21 | 22 |
|
22 | 23 | #include "access/hash.h"
|
23 | 24 | #include "libpq/pqformat.h"
|
@@ -724,7 +725,7 @@ timestamp_date(PG_FUNCTION_ARGS)
|
724 | 725 | if (TIMESTAMP_NOT_FINITE(timestamp))
|
725 | 726 | PG_RETURN_NULL();
|
726 | 727 |
|
727 |
| - if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) |
| 728 | + if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) |
728 | 729 | ereport(ERROR,
|
729 | 730 | (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
730 | 731 | errmsg("timestamp out of range")));
|
@@ -767,7 +768,7 @@ timestamptz_date(PG_FUNCTION_ARGS)
|
767 | 768 | if (TIMESTAMP_NOT_FINITE(timestamp))
|
768 | 769 | PG_RETURN_NULL();
|
769 | 770 |
|
770 |
| - if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) |
| 771 | + if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) |
771 | 772 | ereport(ERROR,
|
772 | 773 | (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
773 | 774 | errmsg("timestamp out of range")));
|
@@ -1327,7 +1328,7 @@ timestamp_time(PG_FUNCTION_ARGS)
|
1327 | 1328 | if (TIMESTAMP_NOT_FINITE(timestamp))
|
1328 | 1329 | PG_RETURN_NULL();
|
1329 | 1330 |
|
1330 |
| - if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL) !=0) |
| 1331 | + if (timestamp2tm(timestamp, NULL, tm, &fsec, NULL, NULL) !=0) |
1331 | 1332 | ereport(ERROR,
|
1332 | 1333 | (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
1333 | 1334 | errmsg("timestamp out of range")));
|
@@ -1364,7 +1365,7 @@ timestamptz_time(PG_FUNCTION_ARGS)
|
1364 | 1365 | if (TIMESTAMP_NOT_FINITE(timestamp))
|
1365 | 1366 | PG_RETURN_NULL();
|
1366 | 1367 |
|
1367 |
| - if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) |
| 1368 | + if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) |
1368 | 1369 | ereport(ERROR,
|
1369 | 1370 | (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
1370 | 1371 | errmsg("timestamp out of range")));
|
@@ -2247,7 +2248,7 @@ timestamptz_timetz(PG_FUNCTION_ARGS)
|
2247 | 2248 | if (TIMESTAMP_NOT_FINITE(timestamp))
|
2248 | 2249 | PG_RETURN_NULL();
|
2249 | 2250 |
|
2250 |
| - if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) !=0) |
| 2251 | + if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn, NULL) !=0) |
2251 | 2252 | ereport(ERROR,
|
2252 | 2253 | (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
2253 | 2254 | errmsg("timestamp out of range")));
|
@@ -2463,53 +2464,60 @@ timetz_part(PG_FUNCTION_ARGS)
|
2463 | 2464 |
|
2464 | 2465 | /* timetz_zone()
|
2465 | 2466 | * Encode time with time zone type with specified time zone.
|
| 2467 | + * Applies DST rules as of the current date. |
2466 | 2468 | */
|
2467 | 2469 | Datum
|
2468 | 2470 | timetz_zone(PG_FUNCTION_ARGS)
|
2469 | 2471 | {
|
2470 | 2472 | text *zone = PG_GETARG_TEXT_P(0);
|
2471 |
| - TimeTzADT *time = PG_GETARG_TIMETZADT_P(1); |
| 2473 | + TimeTzADT *t = PG_GETARG_TIMETZADT_P(1); |
2472 | 2474 | TimeTzADT *result;
|
2473 | 2475 | int tz;
|
2474 |
| - int type, |
2475 |
| - val; |
2476 |
| - char *lowzone; |
2477 |
| - |
2478 |
| - lowzone = downcase_truncate_identifier(VARDATA(zone), |
2479 |
| - VARSIZE(zone) - VARHDRSZ, |
2480 |
| - false); |
2481 |
| - |
2482 |
| - type = DecodeSpecial(0, lowzone, &val); |
| 2476 | + char tzname[TZ_STRLEN_MAX]; |
| 2477 | + int len; |
| 2478 | + pg_tz *tzp; |
| 2479 | + struct pg_tm *tm; |
| 2480 | + pg_time_t now; |
| 2481 | + |
| 2482 | + /* Find the specified timezone */ |
| 2483 | + len = (VARSIZE(zone)-VARHDRSZ>TZ_STRLEN_MAX)?TZ_STRLEN_MAX:(VARSIZE(zone)-VARHDRSZ); |
| 2484 | + memcpy(tzname,VARDATA(zone),len); |
| 2485 | + tzname[len]=0; |
| 2486 | + tzp = pg_tzset(tzname); |
| 2487 | + if (!tzp) { |
| 2488 | + ereport(ERROR, |
| 2489 | + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 2490 | + errmsg("time zone \"%s\" not recognized", tzname))); |
| 2491 | + PG_RETURN_NULL(); |
| 2492 | + } |
2483 | 2493 |
|
2484 |
| - result = (TimeTzADT *) palloc(sizeof(TimeTzADT)); |
| 2494 | + /* Get the offset-from-GMT that is valid today for the selected zone */ |
| 2495 | + if ((now = time(NULL)) < 0 || |
| 2496 | + (tm = pg_localtime(&now, tzp)) == NULL) { |
| 2497 | + ereport(ERROR, |
| 2498 | + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 2499 | + errmsg("could not determine current time"))); |
| 2500 | + PG_RETURN_NULL(); |
| 2501 | + } |
2485 | 2502 |
|
2486 |
| - if (type == TZ || type == DTZ) |
2487 |
| - { |
2488 |
| - tz = val * 60; |
| 2503 | + result = (TimeTzADT *)palloc(sizeof(TimeTzADT)); |
| 2504 | + |
| 2505 | + tz = -tm->tm_gmtoff; |
2489 | 2506 | #ifdef HAVE_INT64_TIMESTAMP
|
2490 |
| - result->time = time->time + (time->zone - tz) * USECS_PER_SEC; |
2491 |
| - while (result->time < INT64CONST(0)) |
2492 |
| - result->time += USECS_PER_DAY; |
2493 |
| - while (result->time >= USECS_PER_DAY) |
2494 |
| - result->time -= USECS_PER_DAY; |
| 2507 | + result->time = t->time + (t->zone - tz) * USECS_PER_SEC; |
| 2508 | + while (result->time < INT64CONST(0)) |
| 2509 | + result->time += USECS_PER_DAY; |
| 2510 | + while (result->time >= USECS_PER_DAY) |
| 2511 | + result->time -= USECS_PER_DAY; |
2495 | 2512 | #else
|
2496 |
| - result->time = time->time + (time->zone - tz); |
2497 |
| - while (result->time < 0) |
2498 |
| - result->time += SECS_PER_DAY; |
2499 |
| - while (result->time >= SECS_PER_DAY) |
2500 |
| - result->time -= SECS_PER_DAY; |
| 2513 | + result->time = t->time + (t->zone - tz); |
| 2514 | + while (result->time < 0) |
| 2515 | + result->time += SECS_PER_DAY; |
| 2516 | + while (result->time >= SECS_PER_DAY) |
| 2517 | + result->time -= SECS_PER_DAY; |
2501 | 2518 | #endif
|
2502 | 2519 |
|
2503 |
| - result->zone = tz; |
2504 |
| - } |
2505 |
| - else |
2506 |
| - { |
2507 |
| - ereport(ERROR, |
2508 |
| - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
2509 |
| - errmsg("time zone \"%s\" not recognized", lowzone))); |
2510 |
| - |
2511 |
| - PG_RETURN_NULL(); |
2512 |
| - } |
| 2520 | + result->zone = tz; |
2513 | 2521 |
|
2514 | 2522 | PG_RETURN_TIMETZADT_P(result);
|
2515 | 2523 | } /* timetz_zone() */
|
|
0 commit comments