Re: where clauses including timstamptz and intervals - Mailing list pgsql-general

From Francisco Olarte
Subject Re: where clauses including timstamptz and intervals
Date
Msg-id CA+bJJbyoPj4k7GLxGMa5V9m_Ag84mhnaP05oz_993=zMMb8nNg@mail.gmail.com
Whole thread Raw
In response to Re: where clauses including timstamptz and intervals  (Ron <ronljohnsonjr@gmail.com>)
List pgsql-general
Ron:

On Fri, Apr 9, 2021 at 5:53 PM Ron <ronljohnsonjr@gmail.com> wrote:
> >> Are these two queries exactly eqivalent? The table is partitioned on
> >> r_time, which is a timestamptz. The explain plans are not exactly the
> >> same. The first wants to scan a partition more than the latter.
> >>
> >> select f.xx from f
> >> where f.r_time  >= '2020-10-01 00:00:00+00'::timestamptz
> >>    and f.r_time < ('2020-10-01 00:00:00+00'::timestamptz + interval '1 month');
> >>
> >> select f.xx from f
> >> where f.r_time  >= '2020-10-01 00:00:00+00'::timestamptz
> >>    and f.r_time < ('2020-11-01 00:00:00+00'::timestamptz);
> > It depends on timezone.
....
> That looks like a flaw in how "month" is calculated.  Whether or not October
> is 744 hours (31 days x 24 hours/day) or 743 hours (subtracting the "fall
> back" hour), one month from 01-Oct-2020 is still 01-Nov-2020.

I've encountered these thing before. What is probably happening is
that your CLIENT TIMEZONE is DST aware.

When you add the interval 1st PG takes the tstz, and converts it to
internal. No problem here, it is a gmt one. The it parses the
interval, again no problem, intervals do not depend on DST.

But then you ask to add them, and timezone + interval is time zone
sensitive. And, counter intuitively to many, tstz does not store
timezone, it marks an instant in time, it just signals that
manipulation to the timezone must be TZ aware, so it does it in your
current timezone.

You probably have ( and if not, you should consider having ) your
partitions defined on GMT, so the time jump at the starty of the month
make it take one more ( are you in Britain/Portugal/Canary islands,
which are +0 in winter +1 in summer, IIRC ? )

If you want to scan exact partitions by specifying arithmetic limits,
set timezone to whichever tz your partitions are partitioned with, or
just name the partitions. If you just want to scan a date range (
thats's what I do a lot ), just trust pg to do the right thing.

Remember, specifying +00 in the input does not make the arithmetic
work in that tz, it works in your tz. I think you could achieve the
desired result by temporarily switching to timestamp without,
something like
('2020-10-01 00:00:00+00'::timestamptz at timezone 'GMT' + interval '1
month') at timezone 'GMT'
IIRC this converts to tstz to ts, then adds there, then converts back
to tstz, my results are:

cdrs=> show timezone;
 TimeZone
----------
 UTC
(1 row)

cdrs=> select ('2020-10-01 00:00:00+00'::timestamptz + interval '1 month');
        ?column?
------------------------
 2020-11-01 00:00:00+00
(1 row)

cdrs=> set timezone to 'Europe/Madrid';
SET

cdrs=> select ('2020-10-01 00:00:00+00'::timestamptz), ('2020-10-01
00:00:00+00'::timestamptz + interval '1 month');
      timestamptz       |        ?column?
------------------------+------------------------
 2020-10-01 02:00:00+02 | 2020-11-01 02:00:00+01
(1 row)

********* diferent UTC hours, same local. (02 but +02 and +01)

cdrs=> select ('2020-10-01 00:00:00+00'::timestamptz), ('2020-10-01
00:00:00+00'::timestamptz at time zone 'utc'+ interval '1 month') at
time zone 'utc';
      timestamptz       |        timezone
------------------------+------------------------
 2020-10-01 02:00:00+02 | 2020-11-01 01:00:00+01
(1 row)

********* Now same UTC hours, different local. ( 02 + 02, 01 + 01 )

If I had monthly partitions rolling at 00 utc, 1st one will nibble the
first hour of an extra one.

TSTZ is hard.

Francisco Olarte.



pgsql-general by date:

Previous
From: Ganesh Korde
Date:
Subject: Re: Who altered the database?
Next
From: Niels Jespersen
Date:
Subject: SV: where clauses including timstamptz and intervals