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...










share|improve this question




























    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...










    share|improve this question


























      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...










      share|improve this question















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 12 at 21:39









      dustinos3

      320216




      320216










      asked Nov 12 at 21:32









      Kevin Bouwkamp

      275




      275
























          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 equal interval '24 hours'. For example, with the session time zone set to CST7CDT, timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' will produce timestamp with time zone '2005-04-03 12:00-06', while adding interval '24 hours' to the same initial timestamp with time zone produces timestamp with time zone '2005-04-03 13:00-06', as there is a change in daylight saving time at 2005-04-03 02:00 in time zone CST7CDT.




          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.






          share|improve this answer





















          • Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
            – Kevin Bouwkamp
            Nov 12 at 22:53


















          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)





          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














             

            draft saved


            draft discarded


















            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

























            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 equal interval '24 hours'. For example, with the session time zone set to CST7CDT, timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' will produce timestamp with time zone '2005-04-03 12:00-06', while adding interval '24 hours' to the same initial timestamp with time zone produces timestamp with time zone '2005-04-03 13:00-06', as there is a change in daylight saving time at 2005-04-03 02:00 in time zone CST7CDT.




            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.






            share|improve this answer





















            • Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
              – Kevin Bouwkamp
              Nov 12 at 22:53















            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 equal interval '24 hours'. For example, with the session time zone set to CST7CDT, timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' will produce timestamp with time zone '2005-04-03 12:00-06', while adding interval '24 hours' to the same initial timestamp with time zone produces timestamp with time zone '2005-04-03 13:00-06', as there is a change in daylight saving time at 2005-04-03 02:00 in time zone CST7CDT.




            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.






            share|improve this answer





















            • Yeah, kinda figured. It makes sense, albeit unfortunate. Thanks
              – Kevin Bouwkamp
              Nov 12 at 22:53













            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 equal interval '24 hours'. For example, with the session time zone set to CST7CDT, timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' will produce timestamp with time zone '2005-04-03 12:00-06', while adding interval '24 hours' to the same initial timestamp with time zone produces timestamp with time zone '2005-04-03 13:00-06', as there is a change in daylight saving time at 2005-04-03 02:00 in time zone CST7CDT.




            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.






            share|improve this answer












            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 equal interval '24 hours'. For example, with the session time zone set to CST7CDT, timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' will produce timestamp with time zone '2005-04-03 12:00-06', while adding interval '24 hours' to the same initial timestamp with time zone produces timestamp with time zone '2005-04-03 13:00-06', as there is a change in daylight saving time at 2005-04-03 02:00 in time zone CST7CDT.




            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.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            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


















            • 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












            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)





            share|improve this answer

























              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)





              share|improve this answer























                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)





                share|improve this answer












                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)






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 13 at 0:19









                Richard Huxton

                14.9k12134




                14.9k12134






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    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





















































                    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







                    Popular posts from this blog

                    mysqli_query(): Empty query in /home/lucindabrummitt/public_html/blog/wp-includes/wp-db.php on line 1924

                    How to change which sound is reproduced for terminal bell?

                    Can I use Tabulator js library in my java Spring + Thymeleaf project?