postgresql timezone conversion 'EST' != '-05'

感情迁移 提交于 2019-12-01 09:08:07

问题


I am running PostgreSQL 9.6.6 on x86_64-pc-linux-gnu and my time zone is set to 'UTC'.

Does anyone know why the results of the following SELECT statements are different?

A)

SELECT timezone('EST', '2017-12-21');
    timezone       
---------------------
2017-12-20 19:00:00

B)

SELECT timezone('-05', '2017-12-21');
      timezone       
---------------------
2017-12-21 05:00:00

According to the pg_timezone_names table -05 should have the same offset as EST... Any thoughts? Thanks.


回答1:


https://www.postgresql.org/docs/current/static/view-pg-timezone-names.html

The view pg_timezone_names provides a list of time zone names that are recognized by SET TIMEZONE

and further:

utc_offset interval Offset from UTC (positive means east of Greenwich)

when you set timezone to 'EST' - you declare that your client is in EST time zone, thus returned time will be adjusted for your tz:

t=# select '2017-12-21'::timestamptz;
      timestamptz
------------------------
 2017-12-21 00:00:00-05
(1 row)

the interval match utc_offset from pg_timezone_names and isequal -05, so it works as expected. (indeed in EST will be 5 hours less then UTC) same result if you set timezone to '-05'.

Both -05 and EST give same result for SET TIMEZONE as described in docs.

Now you answer reconciles with docs on using interval: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-ZONECONVERT

In these expressions, the desired time zone zone can be specified either as a text string (e.g., 'PST') or as an interval (e.g., INTERVAL '-08:00').

following these rules it works as well:

t=# select '2017-12-21'::timestamptz at time zone 'EST';
      timezone
---------------------
 2017-12-20 19:00:00
(1 row)

t=# select '2017-12-21'::timestamptz at time zone interval '-05:00';
      timezone
---------------------
 2017-12-20 19:00:00
(1 row)

but further, docs say:

In the text case, a time zone name can be specified in any of the ways described in Section 8.5.3.

which is https://www.postgresql.org/docs/current/static/datatype-datetime.html#DATATYPE-TIMEZONES

PostgreSQL allows you to specify time zones in three different forms:

  • recognized time zone names are listed in the pg_timezone_names
  • recognized abbreviations are listed in the pg_timezone_abbrevs
  • POSIX-style time zone specifications of the form STDoffset or STDoffsetDST

(formatting mine)

and lastly:

One should be wary that the POSIX-style time zone feature can lead to silently accepting bogus input...Another issue to keep in mind is that in POSIX time zone names, positive offsets are used for locations west of Greenwich. Everywhere else, PostgreSQL follows the ISO-8601 convention that positive timezone offsets are east of Greenwich.

TL;DR

So in short - when you define '-05' as text (not interval) input for timezone() function or AT TIME ZONE directive (effectively same) Postgres thinks this is an attempt to use POSIX style time zone and thus inverts sign, thus you get "opposite" result...

a simple demonstration of this documented inversion:

t=# select '2017-12-21'::timestamptz at time zone '05';
      timezone
---------------------
 2017-12-20 19:00:00
(1 row)



回答2:


Okay I think I found an answer to my own question:

According to the PostgreSQL docs, section 9.9.3 at the following link https://www.postgresql.org/docs/9.6/static/functions-datetime.html

In these expressions, the desired time zone zone can be specified either as a text string (e.g., 'PST') or as an interval (e.g., INTERVAL '-08:00'). In the text case, a time zone name can be specified in any of the ways described in Section 8.5.3.

So using the INTERVAL syntax, the following appears to work:

SELECT timezone(INTERVAL '-05:00', '2017-12-21');
      timezone       
---------------------
2017-12-20 19:00:00

I think it is still curious, what exactly SELECT timezone('-05', '2017-12-21'); means, as the following also provides the expected result (with the addition of a TZ offset):

SELECT timezone('-05', '2017-12-21'::timestamp);
        timezone        
------------------------
2017-12-20 19:00:00+00


来源:https://stackoverflow.com/questions/48013068/postgresql-timezone-conversion-est-05

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!