Re: Interval in hours but not in days Leap second not taken into account

From: Thomas Munro <thomas(dot)munro(at)gmail(dot)com>
To: PALAYRET Jacques <jacques(dot)palayret(at)meteo(dot)fr>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: Interval in hours but not in days Leap second not taken into account
Date: 2023-03-01 01:29:20
Message-ID: CA+hUKGLU9Don4YHnfdzn0eeWQsUu8GJDaLiUAefLLT6=mmeGoQ@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Mon, Feb 27, 2023 at 8:26 PM PALAYRET Jacques
<jacques(dot)palayret(at)meteo(dot)fr> wrote:
> # PostgreSQL does not take into account the additional second (leap second) in some calendar days ; eg. 2016, 31 dec. :
> SELECT to_timestamp('20170102 10:11:12','yyyymmdd hh24:mi:ss') - to_timestamp('20161230 00:00:00','yyyymmdd hh24:mi:ss') intervalle ;
> intervalle
> -----------------
> 3 days 10:11:12

Bonjour Jacques,

Just for fun:

postgres=# SELECT utc_to_tai(to_timestamp('20170102
10:11:12','yyyymmdd hh24:mi:ss')) -
utc_to_tai(to_timestamp('20161230 00:00:00','yyyymmdd
hh24:mi:ss')) intervalle;
intervalle
-----------------
3 days 10:11:13
(1 row)

PostgreSQL could, in theory, provide built-in UTC/TAI conversions
functions using a leap second table that would be updated in each
minor release, considering that the leap second table is included in
the tzdata package that PostgreSQL vendors (ie includes a copy of),
but it doesn't do anything like that or know anything about leap
seconds. Here's a quick and dirty low technology version of the
above:

CREATE TABLE leap_seconds (time timestamptz primary key, off int);

-- refresh leap second table from ietf.org using not-very-secure hairy
shell code
BEGIN;
CREATE TEMP TABLE import_leap_seconds (s int8, off int);
COPY import_leap_seconds FROM PROGRAM 'curl -s
https://www.ietf.org/timezones/data/leap-seconds.list | grep -v ''^#''
| cut -f1,2';
TRUNCATE TABLE leap_seconds;
INSERT INTO leap_seconds (time, off)
SELECT '1900-01-01 00:00:00Z'::timestamptz + interval '1 second' * s, off
FROM import_leap_seconds;
DROP TABLE import_leap_seconds;
COMMIT;

CREATE OR REPLACE FUNCTION leap_seconds_before_utc_time(t timestamptz)
RETURNS int STRICT LANGUAGE SQL AS
$$
SELECT off FROM leap_seconds WHERE time <= t ORDER BY time DESC
FETCH FIRST ROW ONLY
$$;

CREATE OR REPLACE FUNCTION utc_to_tai(t timestamptz)
RETURNS timestamptz STRICT LANGUAGE SQL AS
$$
SELECT t + interval '1 second' * coalesce(leap_seconds_before_utc_time(t), 0);
$$;

CREATE OR REPLACE FUNCTION tai_to_utc(t timestamptz)
RETURNS timestamptz STRICT LANGUAGE SQL AS
$$
SELECT t - interval '1 second' * coalesce(leap_seconds_before_utc_time(t), 0);
$$;

In response to

Browse pgsql-general by date

  From Date Subject
Next Message Arthur Ramsey 2023-03-01 16:32:23 Failed upgrade from 12.11 to 14.4
Previous Message Thomas Munro 2023-02-28 21:30:09 Re: 13.x, stream replication and locale(?) issues