generate_series over daylight savings change - varied results depending on server timezone
up vote
1
down vote
favorite
When my postgres server is in the America/New_York timezone, or I use SET SESSION TIME ZONE 'America/New_York'
, generate_series respects the daylight savings change and I can get the proper epoch or point in time that I want:
postgres=# SET SESSION TIME ZONE 'America/New_York';
SET
postgres=#
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 00:00:00-04 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 00:00:00-04 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 00:00:00-05 | 1541394000 | 2018-11-05 00:00:00
2018-11-06 00:00:00-05 | 1541480400 | 2018-11-06 00:00:00
(4 rows)
But when my server is in UTC as it is in production, generate_series does not respect the daylight savings change:
postgres=# SET SESSION TIME ZONE 'UTC';
SET
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 04:00:00+00 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 04:00:00+00 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 04:00:00+00 | 1541390400 | 2018-11-04 23:00:00
2018-11-06 04:00:00+00 | 1541476800 | 2018-11-05 23:00:00
(4 rows)
Notice 11/4 and 11/5 have not been adjusted for the DST change.
Is there any way around this without setting the session time zone when I query?
Using postgres 9.6...
database postgresql timezone dst postgresql-9.6
add a comment |
up vote
1
down vote
favorite
When my postgres server is in the America/New_York timezone, or I use SET SESSION TIME ZONE 'America/New_York'
, generate_series respects the daylight savings change and I can get the proper epoch or point in time that I want:
postgres=# SET SESSION TIME ZONE 'America/New_York';
SET
postgres=#
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 00:00:00-04 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 00:00:00-04 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 00:00:00-05 | 1541394000 | 2018-11-05 00:00:00
2018-11-06 00:00:00-05 | 1541480400 | 2018-11-06 00:00:00
(4 rows)
But when my server is in UTC as it is in production, generate_series does not respect the daylight savings change:
postgres=# SET SESSION TIME ZONE 'UTC';
SET
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 04:00:00+00 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 04:00:00+00 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 04:00:00+00 | 1541390400 | 2018-11-04 23:00:00
2018-11-06 04:00:00+00 | 1541476800 | 2018-11-05 23:00:00
(4 rows)
Notice 11/4 and 11/5 have not been adjusted for the DST change.
Is there any way around this without setting the session time zone when I query?
Using postgres 9.6...
database postgresql timezone dst postgresql-9.6
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
When my postgres server is in the America/New_York timezone, or I use SET SESSION TIME ZONE 'America/New_York'
, generate_series respects the daylight savings change and I can get the proper epoch or point in time that I want:
postgres=# SET SESSION TIME ZONE 'America/New_York';
SET
postgres=#
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 00:00:00-04 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 00:00:00-04 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 00:00:00-05 | 1541394000 | 2018-11-05 00:00:00
2018-11-06 00:00:00-05 | 1541480400 | 2018-11-06 00:00:00
(4 rows)
But when my server is in UTC as it is in production, generate_series does not respect the daylight savings change:
postgres=# SET SESSION TIME ZONE 'UTC';
SET
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 04:00:00+00 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 04:00:00+00 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 04:00:00+00 | 1541390400 | 2018-11-04 23:00:00
2018-11-06 04:00:00+00 | 1541476800 | 2018-11-05 23:00:00
(4 rows)
Notice 11/4 and 11/5 have not been adjusted for the DST change.
Is there any way around this without setting the session time zone when I query?
Using postgres 9.6...
database postgresql timezone dst postgresql-9.6
When my postgres server is in the America/New_York timezone, or I use SET SESSION TIME ZONE 'America/New_York'
, generate_series respects the daylight savings change and I can get the proper epoch or point in time that I want:
postgres=# SET SESSION TIME ZONE 'America/New_York';
SET
postgres=#
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 00:00:00-04 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 00:00:00-04 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 00:00:00-05 | 1541394000 | 2018-11-05 00:00:00
2018-11-06 00:00:00-05 | 1541480400 | 2018-11-06 00:00:00
(4 rows)
But when my server is in UTC as it is in production, generate_series does not respect the daylight savings change:
postgres=# SET SESSION TIME ZONE 'UTC';
SET
postgres=# with seq(ts) as (select * from generate_series('2018-11-03 00:00:00.000 -04:00', '2018-11-06 13:40:39.067 -05:00', '1d'::interval))
postgres-# select ts, extract(epoch from ts) as epoch, ts at time zone 'America/New_York' as eastern
postgres-# from seq;
ts | epoch | eastern
------------------------+------------+---------------------
2018-11-03 04:00:00+00 | 1541217600 | 2018-11-03 00:00:00
2018-11-04 04:00:00+00 | 1541304000 | 2018-11-04 00:00:00
2018-11-05 04:00:00+00 | 1541390400 | 2018-11-04 23:00:00
2018-11-06 04:00:00+00 | 1541476800 | 2018-11-05 23:00:00
(4 rows)
Notice 11/4 and 11/5 have not been adjusted for the DST change.
Is there any way around this without setting the session time zone when I query?
Using postgres 9.6...
database postgresql timezone dst postgresql-9.6
database postgresql timezone dst postgresql-9.6
edited Nov 12 at 21:39
dustinos3
320216
320216
asked Nov 12 at 21:32
Kevin Bouwkamp
275
275
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
The session time zone is what controls how an interval of 1 day is interpreted, so I think the answer to your question is simply, no.
The Postgres docs explain this as follows:
When adding an interval value to (or subtracting an interval value from) a timestamp with time zone value, the days component advances or decrements the date of the timestamp with time zone by the indicated number of days. Across daylight saving time changes (when the session time zone is set to a time zone that recognizes DST), this means
interval '1 day'
does not necessarily equalinterval '24 hours'
. For example, with the session time zone set toCST7CDT
,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day'
will producetimestamp with time zone '2005-04-03 12:00-06'
, while addinginterval '24 hours'
to the same initial timestamp with time zone producestimestamp with time zone '2005-04-03 13:00-06'
, as there is a change in daylight saving time at2005-04-03 02:00
in time zoneCST7CDT
.
As far as I am aware, there's no other mechanism of how to tell an interval to be interpreted in a specific time zone, other than setting that as the session time zone. In other words, I think you'd be looking for something like '1 day tz America/New_York'::interval
and I don't believe such a syntax exists.
Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
– Kevin Bouwkamp
Nov 12 at 22:53
add a comment |
up vote
1
down vote
You can set the timezone automatically upon connection for specific users (ALTER USER), or for a specific database (ALTER DATABASE).
The only other way I can think of is with a function.
BEGIN;
CREATE FUNCTION f1() RETURNS SETOF timestamptz
AS $$
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
$$
LANGUAGE sql
SET timezone = 'America/New_York';
SET timezone = 'UTC';
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
SELECT * FROM f1();
ROLLBACK;
Produces:
generate_series
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 04:00:00+00
2018-11-06 04:00:00+00
(4 rows)
f1
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 05:00:00+00
2018-11-06 05:00:00+00
(4 rows)
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
The session time zone is what controls how an interval of 1 day is interpreted, so I think the answer to your question is simply, no.
The Postgres docs explain this as follows:
When adding an interval value to (or subtracting an interval value from) a timestamp with time zone value, the days component advances or decrements the date of the timestamp with time zone by the indicated number of days. Across daylight saving time changes (when the session time zone is set to a time zone that recognizes DST), this means
interval '1 day'
does not necessarily equalinterval '24 hours'
. For example, with the session time zone set toCST7CDT
,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day'
will producetimestamp with time zone '2005-04-03 12:00-06'
, while addinginterval '24 hours'
to the same initial timestamp with time zone producestimestamp with time zone '2005-04-03 13:00-06'
, as there is a change in daylight saving time at2005-04-03 02:00
in time zoneCST7CDT
.
As far as I am aware, there's no other mechanism of how to tell an interval to be interpreted in a specific time zone, other than setting that as the session time zone. In other words, I think you'd be looking for something like '1 day tz America/New_York'::interval
and I don't believe such a syntax exists.
Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
– Kevin Bouwkamp
Nov 12 at 22:53
add a comment |
up vote
1
down vote
accepted
The session time zone is what controls how an interval of 1 day is interpreted, so I think the answer to your question is simply, no.
The Postgres docs explain this as follows:
When adding an interval value to (or subtracting an interval value from) a timestamp with time zone value, the days component advances or decrements the date of the timestamp with time zone by the indicated number of days. Across daylight saving time changes (when the session time zone is set to a time zone that recognizes DST), this means
interval '1 day'
does not necessarily equalinterval '24 hours'
. For example, with the session time zone set toCST7CDT
,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day'
will producetimestamp with time zone '2005-04-03 12:00-06'
, while addinginterval '24 hours'
to the same initial timestamp with time zone producestimestamp with time zone '2005-04-03 13:00-06'
, as there is a change in daylight saving time at2005-04-03 02:00
in time zoneCST7CDT
.
As far as I am aware, there's no other mechanism of how to tell an interval to be interpreted in a specific time zone, other than setting that as the session time zone. In other words, I think you'd be looking for something like '1 day tz America/New_York'::interval
and I don't believe such a syntax exists.
Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
– Kevin Bouwkamp
Nov 12 at 22:53
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
The session time zone is what controls how an interval of 1 day is interpreted, so I think the answer to your question is simply, no.
The Postgres docs explain this as follows:
When adding an interval value to (or subtracting an interval value from) a timestamp with time zone value, the days component advances or decrements the date of the timestamp with time zone by the indicated number of days. Across daylight saving time changes (when the session time zone is set to a time zone that recognizes DST), this means
interval '1 day'
does not necessarily equalinterval '24 hours'
. For example, with the session time zone set toCST7CDT
,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day'
will producetimestamp with time zone '2005-04-03 12:00-06'
, while addinginterval '24 hours'
to the same initial timestamp with time zone producestimestamp with time zone '2005-04-03 13:00-06'
, as there is a change in daylight saving time at2005-04-03 02:00
in time zoneCST7CDT
.
As far as I am aware, there's no other mechanism of how to tell an interval to be interpreted in a specific time zone, other than setting that as the session time zone. In other words, I think you'd be looking for something like '1 day tz America/New_York'::interval
and I don't believe such a syntax exists.
The session time zone is what controls how an interval of 1 day is interpreted, so I think the answer to your question is simply, no.
The Postgres docs explain this as follows:
When adding an interval value to (or subtracting an interval value from) a timestamp with time zone value, the days component advances or decrements the date of the timestamp with time zone by the indicated number of days. Across daylight saving time changes (when the session time zone is set to a time zone that recognizes DST), this means
interval '1 day'
does not necessarily equalinterval '24 hours'
. For example, with the session time zone set toCST7CDT
,timestamp with time zone '2005-04-02 12:00-07' + interval '1 day'
will producetimestamp with time zone '2005-04-03 12:00-06'
, while addinginterval '24 hours'
to the same initial timestamp with time zone producestimestamp with time zone '2005-04-03 13:00-06'
, as there is a change in daylight saving time at2005-04-03 02:00
in time zoneCST7CDT
.
As far as I am aware, there's no other mechanism of how to tell an interval to be interpreted in a specific time zone, other than setting that as the session time zone. In other words, I think you'd be looking for something like '1 day tz America/New_York'::interval
and I don't believe such a syntax exists.
answered Nov 12 at 22:24
Matt Johnson
133k40270393
133k40270393
Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
– Kevin Bouwkamp
Nov 12 at 22:53
add a comment |
Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
– Kevin Bouwkamp
Nov 12 at 22:53
Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
– Kevin Bouwkamp
Nov 12 at 22:53
Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
– Kevin Bouwkamp
Nov 12 at 22:53
add a comment |
up vote
1
down vote
You can set the timezone automatically upon connection for specific users (ALTER USER), or for a specific database (ALTER DATABASE).
The only other way I can think of is with a function.
BEGIN;
CREATE FUNCTION f1() RETURNS SETOF timestamptz
AS $$
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
$$
LANGUAGE sql
SET timezone = 'America/New_York';
SET timezone = 'UTC';
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
SELECT * FROM f1();
ROLLBACK;
Produces:
generate_series
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 04:00:00+00
2018-11-06 04:00:00+00
(4 rows)
f1
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 05:00:00+00
2018-11-06 05:00:00+00
(4 rows)
add a comment |
up vote
1
down vote
You can set the timezone automatically upon connection for specific users (ALTER USER), or for a specific database (ALTER DATABASE).
The only other way I can think of is with a function.
BEGIN;
CREATE FUNCTION f1() RETURNS SETOF timestamptz
AS $$
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
$$
LANGUAGE sql
SET timezone = 'America/New_York';
SET timezone = 'UTC';
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
SELECT * FROM f1();
ROLLBACK;
Produces:
generate_series
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 04:00:00+00
2018-11-06 04:00:00+00
(4 rows)
f1
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 05:00:00+00
2018-11-06 05:00:00+00
(4 rows)
add a comment |
up vote
1
down vote
up vote
1
down vote
You can set the timezone automatically upon connection for specific users (ALTER USER), or for a specific database (ALTER DATABASE).
The only other way I can think of is with a function.
BEGIN;
CREATE FUNCTION f1() RETURNS SETOF timestamptz
AS $$
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
$$
LANGUAGE sql
SET timezone = 'America/New_York';
SET timezone = 'UTC';
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
SELECT * FROM f1();
ROLLBACK;
Produces:
generate_series
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 04:00:00+00
2018-11-06 04:00:00+00
(4 rows)
f1
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 05:00:00+00
2018-11-06 05:00:00+00
(4 rows)
You can set the timezone automatically upon connection for specific users (ALTER USER), or for a specific database (ALTER DATABASE).
The only other way I can think of is with a function.
BEGIN;
CREATE FUNCTION f1() RETURNS SETOF timestamptz
AS $$
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
$$
LANGUAGE sql
SET timezone = 'America/New_York';
SET timezone = 'UTC';
SELECT generate_series('2018-11-03 00:00:00-04', '2018-11-06 00:00:00-05', interval '1 day');
SELECT * FROM f1();
ROLLBACK;
Produces:
generate_series
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 04:00:00+00
2018-11-06 04:00:00+00
(4 rows)
f1
------------------------
2018-11-03 04:00:00+00
2018-11-04 04:00:00+00
2018-11-05 05:00:00+00
2018-11-06 05:00:00+00
(4 rows)
answered Nov 13 at 0:19
Richard Huxton
14.9k12134
14.9k12134
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53270410%2fgenerate-series-over-daylight-savings-change-varied-results-depending-on-serve%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown