|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.189 2008/05/04 23:19:23 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.190 2008/07/07 18:09:46 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -4410,58 +4410,62 @@ timestamp_zone(PG_FUNCTION_ARGS) |
4410 | 4410 | Timestamp timestamp = PG_GETARG_TIMESTAMP(1); |
4411 | 4411 | TimestampTz result; |
4412 | 4412 | int tz; |
4413 | | - pg_tz *tzp; |
4414 | 4413 | char tzname[TZ_STRLEN_MAX + 1]; |
| 4414 | + char *lowzone; |
| 4415 | + int type, |
| 4416 | + val; |
| 4417 | + pg_tz *tzp; |
4415 | 4418 |
|
4416 | 4419 | if (TIMESTAMP_NOT_FINITE(timestamp)) |
4417 | 4420 | PG_RETURN_TIMESTAMPTZ(timestamp); |
4418 | 4421 |
|
4419 | 4422 | /* |
4420 | | - * Look up the requested timezone. First we look in the timezone database |
4421 | | - * (to handle cases like "America/New_York"), and if that fails, we look |
4422 | | - * in the date token table (to handle cases like "EST"). |
| 4423 | + * Look up the requested timezone. First we look in the date token table |
| 4424 | + * (to handle cases like "EST"), and if that fails, we look in the |
| 4425 | + * timezone database (to handle cases like "America/New_York"). (This |
| 4426 | + * matches the order in which timestamp input checks the cases; it's |
| 4427 | + * important because the timezone database unwisely uses a few zone names |
| 4428 | + * that are identical to offset abbreviations.) |
4423 | 4429 | */ |
4424 | 4430 | text_to_cstring_buffer(zone, tzname, sizeof(tzname)); |
4425 | | - tzp = pg_tzset(tzname); |
4426 | | - if (tzp) |
4427 | | - { |
4428 | | - /* Apply the timezone change */ |
4429 | | - struct pg_tm tm; |
4430 | | - fsec_t fsec; |
| 4431 | + lowzone = downcase_truncate_identifier(tzname, |
| 4432 | + strlen(tzname), |
| 4433 | + false); |
4431 | 4434 |
|
4432 | | - if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0) |
4433 | | - ereport(ERROR, |
4434 | | - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), |
4435 | | - errmsg("timestamp out of range"))); |
4436 | | - tz = DetermineTimeZoneOffset(&tm, tzp); |
4437 | | - if (tm2timestamp(&tm, fsec, &tz, &result) != 0) |
4438 | | - ereport(ERROR, |
4439 | | - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4440 | | - errmsg("could not convert to time zone \"%s\"", |
4441 | | - tzname))); |
| 4435 | + type = DecodeSpecial(0, lowzone, &val); |
| 4436 | + |
| 4437 | + if (type == TZ || type == DTZ) |
| 4438 | + { |
| 4439 | + tz = -(val * 60); |
| 4440 | + result = dt2local(timestamp, tz); |
4442 | 4441 | } |
4443 | 4442 | else |
4444 | 4443 | { |
4445 | | - char *lowzone; |
4446 | | - int type, |
4447 | | - val; |
4448 | | - |
4449 | | - lowzone = downcase_truncate_identifier(tzname, |
4450 | | - strlen(tzname), |
4451 | | - false); |
4452 | | - type = DecodeSpecial(0, lowzone, &val); |
| 4444 | + tzp = pg_tzset(tzname); |
| 4445 | + if (tzp) |
| 4446 | + { |
| 4447 | + /* Apply the timezone change */ |
| 4448 | + struct pg_tm tm; |
| 4449 | + fsec_t fsec; |
4453 | 4450 |
|
4454 | | - if (type == TZ || type == DTZ) |
4455 | | - tz = -(val * 60); |
| 4451 | + if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, tzp) != 0) |
| 4452 | + ereport(ERROR, |
| 4453 | + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), |
| 4454 | + errmsg("timestamp out of range"))); |
| 4455 | + tz = DetermineTimeZoneOffset(&tm, tzp); |
| 4456 | + if (tm2timestamp(&tm, fsec, &tz, &result) != 0) |
| 4457 | + ereport(ERROR, |
| 4458 | + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 4459 | + errmsg("could not convert to time zone \"%s\"", |
| 4460 | + tzname))); |
| 4461 | + } |
4456 | 4462 | else |
4457 | 4463 | { |
4458 | 4464 | ereport(ERROR, |
4459 | 4465 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4460 | 4466 | errmsg("time zone \"%s\" not recognized", tzname))); |
4461 | | - tz = 0; /* keep compiler quiet */ |
| 4467 | + result = 0; /* keep compiler quiet */ |
4462 | 4468 | } |
4463 | | - |
4464 | | - result = dt2local(timestamp, tz); |
4465 | 4469 | } |
4466 | 4470 |
|
4467 | 4471 | PG_RETURN_TIMESTAMPTZ(result); |
@@ -4580,57 +4584,61 @@ timestamptz_zone(PG_FUNCTION_ARGS) |
4580 | 4584 | TimestampTz timestamp = PG_GETARG_TIMESTAMPTZ(1); |
4581 | 4585 | Timestamp result; |
4582 | 4586 | int tz; |
4583 | | - pg_tz *tzp; |
4584 | 4587 | char tzname[TZ_STRLEN_MAX + 1]; |
| 4588 | + char *lowzone; |
| 4589 | + int type, |
| 4590 | + val; |
| 4591 | + pg_tz *tzp; |
4585 | 4592 |
|
4586 | 4593 | if (TIMESTAMP_NOT_FINITE(timestamp)) |
4587 | 4594 | PG_RETURN_TIMESTAMP(timestamp); |
4588 | 4595 |
|
4589 | 4596 | /* |
4590 | | - * Look up the requested timezone. First we look in the timezone database |
4591 | | - * (to handle cases like "America/New_York"), and if that fails, we look |
4592 | | - * in the date token table (to handle cases like "EST"). |
| 4597 | + * Look up the requested timezone. First we look in the date token table |
| 4598 | + * (to handle cases like "EST"), and if that fails, we look in the |
| 4599 | + * timezone database (to handle cases like "America/New_York"). (This |
| 4600 | + * matches the order in which timestamp input checks the cases; it's |
| 4601 | + * important because the timezone database unwisely uses a few zone names |
| 4602 | + * that are identical to offset abbreviations.) |
4593 | 4603 | */ |
4594 | 4604 | text_to_cstring_buffer(zone, tzname, sizeof(tzname)); |
4595 | | - tzp = pg_tzset(tzname); |
4596 | | - if (tzp) |
4597 | | - { |
4598 | | - /* Apply the timezone change */ |
4599 | | - struct pg_tm tm; |
4600 | | - fsec_t fsec; |
| 4605 | + lowzone = downcase_truncate_identifier(tzname, |
| 4606 | + strlen(tzname), |
| 4607 | + false); |
4601 | 4608 |
|
4602 | | - if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0) |
4603 | | - ereport(ERROR, |
4604 | | - (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), |
4605 | | - errmsg("timestamp out of range"))); |
4606 | | - if (tm2timestamp(&tm, fsec, NULL, &result) != 0) |
4607 | | - ereport(ERROR, |
4608 | | - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4609 | | - errmsg("could not convert to time zone \"%s\"", |
4610 | | - tzname))); |
| 4609 | + type = DecodeSpecial(0, lowzone, &val); |
| 4610 | + |
| 4611 | + if (type == TZ || type == DTZ) |
| 4612 | + { |
| 4613 | + tz = val * 60; |
| 4614 | + result = dt2local(timestamp, tz); |
4611 | 4615 | } |
4612 | 4616 | else |
4613 | 4617 | { |
4614 | | - char *lowzone; |
4615 | | - int type, |
4616 | | - val; |
4617 | | - |
4618 | | - lowzone = downcase_truncate_identifier(tzname, |
4619 | | - strlen(tzname), |
4620 | | - false); |
4621 | | - type = DecodeSpecial(0, lowzone, &val); |
| 4618 | + tzp = pg_tzset(tzname); |
| 4619 | + if (tzp) |
| 4620 | + { |
| 4621 | + /* Apply the timezone change */ |
| 4622 | + struct pg_tm tm; |
| 4623 | + fsec_t fsec; |
4622 | 4624 |
|
4623 | | - if (type == TZ || type == DTZ) |
4624 | | - tz = val * 60; |
| 4625 | + if (timestamp2tm(timestamp, &tz, &tm, &fsec, NULL, tzp) != 0) |
| 4626 | + ereport(ERROR, |
| 4627 | + (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), |
| 4628 | + errmsg("timestamp out of range"))); |
| 4629 | + if (tm2timestamp(&tm, fsec, NULL, &result) != 0) |
| 4630 | + ereport(ERROR, |
| 4631 | + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 4632 | + errmsg("could not convert to time zone \"%s\"", |
| 4633 | + tzname))); |
| 4634 | + } |
4625 | 4635 | else |
4626 | 4636 | { |
4627 | 4637 | ereport(ERROR, |
4628 | 4638 | (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
4629 | 4639 | errmsg("time zone \"%s\" not recognized", tzname))); |
4630 | | - tz = 0; /* keep compiler quiet */ |
| 4640 | + result = 0; /* keep compiler quiet */ |
4631 | 4641 | } |
4632 | | - |
4633 | | - result = dt2local(timestamp, tz); |
4634 | 4642 | } |
4635 | 4643 |
|
4636 | 4644 | PG_RETURN_TIMESTAMP(result); |
|
0 commit comments