postgresql date types - ghdrako/doc_snipets GitHub Wiki
-
https://www.postgresql.org/docs/current/datatype-datetime.html
-
https://tapoueh.org/blog/2018/04/postgresql-data-types-date-timestamp-and-time-zones/
-
https://www.postgresql.org/docs/current/view-pg-settings.html.
Convert timestamp to date prevent using index
Wrong | good |
---|---|
scheduled_departure ::date BETWEEN '2023-08-17' AND '2023-08-18' | scheduled_departure >='2023-08-17' AND scheduled_departure <'2023-08-19' |
update_ts::date=CURRENT_DATE | update_ts>= CURRENT_DATE AND update_ts< CURRENT_DATE +1 |
coalesce(actual_departure, scheduled_departure) BETWEEN '2023-08-17' AND '2023-08-18' | (actual_departure BETWEEN '2023-08-17' AND '2023-08-18') OR (actual_departure IS NULL AND scheduled_departure BETWEEN '2023-08-17' AND '2023-08-18') |
Decorated literal
we decorate the literal with its data type so that PostgreSQL doesn’t have to guess what it is.
select date '2010-02-20';
select timestamp '2024-10-01 00:00:00';
Convert timestamp to date
select DATE(CURRENT_TIMESTAMP);
select CURRENT_TIMESTAMP::date;
Extract from date
- https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
- https://www.postgresql.org/docs/current/functions-formatting.html
select date::date,
extract('isodow' from date) as dow,
to_char(date, 'dy') as day,
extract('isoyear' from date) as "iso year",
extract('week' from date) as week,
extract('day' from
(date + interval '2 month - 1 day')
)
as feb,
extract('year' from date) as year,
extract('day' from
(date + interval '2 month - 1 day')
) = 29
as leap
from generate_series(date '2000-01-01',
date '2010-01-01',
interval '1 year')
as t(date);
date │ dow │ day │ iso year │ week │ feb │ year │ leap
2000-01-01 │ 6 │ sat │ 1999 │ 52 │ 29 │ 2000 │ t
2001-01-01 │ 1 │ mon │ 2001 │ 1 │ 28 │ 2001 │ f
2002-01-01 │ 2 │ tue │ 2002 │ 1 │ 28 │ 2002 │ f
2003-01-01 │ 3 │ wed │ 2003 │ 1 │ 28 │ 2003 │ f
2004-01-01 │ 4 │ thu │ 2004 │ 1 │ 29 │ 2004 │ t
2005-01-01 │ 6 │ sat │ 2004 │ 53 │ 28 │ 2005 │ f
2006-01-01 │ 7 │ sun │ 2005 │ 52 │ 28 │ 2006 │ f
2007-01-01 │ 1 │ mon │ 2007 │ 1 │ 28 │ 2007 │ f
2008-01-01 │ 2 │ tue │ 2008 │ 1 │ 29 │ 2008 │ t
2009-01-01 │ 4 │ thu │ 2009 │ 1 │ 28 │ 2009 │ f
2010-01-01 │ 5 │ fri │ 2009 │ 53 │ 28 │ 2010 │ f
(11 rows) It
By definition, ISO weeks start on Mondays and the ??rst week of a year contains January 4 of that year. In other words, the first Thurs-day of a year is in week 1 of that year.
\set beginning '2017-04-01'
\set months 3
Select name
From race
where date >= date :'beginning'
and date < date :'beginning'
+ :months * interval '1 month';
Java jdbc exeute analyze
final Statement st2 = connection.createStatement();
st2.executeUpdate("VACUUM FULL ANALYZE VERBOSE");
st2.close();
show DateStyle;
select * from pg_settings where name ='DateStyle';
name | DateStyle
setting | ISO, MDY
[..]
sourcefile |
sourceline |
pending_restart | f
Using the pg_settings
view, we
can view the parameters set in the postgresql.conf
configuration file. In the preceding
result, we can see that the configuration for displaying the date is MDY (month/day/year).
If we want to change this parameter globally, we have to edit the postgresql.conf file.
set DateStyle='ISO MDY' ;
select '12-31-2020'::date;
date
------------
2020-12-31
select to_date('31/12/2020','dd/mm/yyyy') ;
to_date
------------
2020-12-31
create table new_posts as select pk,title,created_on::timestamp
with time zone as created_on_t, created_on::timestamp without time zone as
create_on_nt from posts;
extract(y From current_date) as year
DATE_TRUNC('month', now())
date_trunc('datepart', field)
datepart: millennium,century,decade,year,quarter,month,week,day,hour,minute,second,milliseconds,microseconds
SELECT DATE_TRUNC('hour', TIMESTAMP '2017-03-17 02:09:30');
SELECT date_trunc('minute', TIMESTAMP '2017-03-17 02:09:30');
SELECT
date_trunc('month', rental_date) m,
COUNT (rental_id)
FROM
rental
GROUP BY
m
ORDER BY
m;
Convert to char
select to_date(20230219',YYYYMMDD');
select to_timestamp('28 Oct 2020 09:36:47 am','DD Mon YYYY HH:MI:SS AM');
select to_char(clock_change_date, 'Mon DD, YYYY') from clock_change;
SELECT TO_CHAR('2016-08-12 16:40:32'::TIMESTAMP, 'DD Mon YYYY HH:MI:SSPM');
SELECT TO_CHAR('2016-08-12 16:40:32'::TIMESTAMP,'"Today is "FMDay", the "DDth" day of the month of "FMMonth" of "YYYY');
SELECT TO_CHAR('2016-08-12 16:40:32'::TIMESTAMP, 'TMDay, DD" de "TMMonth" del año "YYYY'); -- TM (translation mode) modifier
--This option uses the localization setting of the server running PostgreSQL or the client connecting to it.
last day of mont
SELECT (DATE_TRUNC('MONTH', ('201608'||'01')::DATE) + INTERVAL '1 MONTH - 1 day')::DATE;
TIMESTAMP and TIMESTAMPTZ
PostgreSQL provides you with two temporal data types for handling timestamp:
- timestamp: a timestamp without timezone one.
- timestamptz: timestamp with a timezone.
PostgreSQL stores the timestamptz in UTC value.
- When you insert a value into a timestamptz column, PostgreSQL converts the timestamptz value into a UTC value and stores the UTC value in the table.
- When you query timestamptz from the database, PostgreSQL converts the UTC value back to the time value of the timezone set by the database server, the user, or the current database connection.
SELECT
pg_column_size('2000-01-01 00:00:00 +00:00'::timestamp) as "timestamp byte size",
pg_column_size('2000-01-01 00:00:00 +00:00'::timestamptz) as "timestamptz byte size";
+--------------------+-----------------------+
|timestamp byte size | timestamptz byte size |
+--------------------+-----------------------+
| 8 | 8 |
+--------------------+-----------------------+
select pg_column_size(timestamp without time zone 'now'),
pg_column_size(timestamp with time zone 'now');
PostgreSQL doesn’t store the time zone they come from with your timestamp.
For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system’s TimeZone parameter, and is converted to UTC using the offset for the timezone zone.
CREATE TABLE timestamp_demo (
ts TIMESTAMP,
tstz TIMESTAMPTZ
);
SET timezone = 'America/Los_Angeles';
SHOW TIMEZONE;
INSERT INTO timestamp_demo (ts, tstz)
VALUES('2016-06-22 19:10:25-07','2016-06-22 19:10:25-07');
SELECT
ts, tstz
FROM
timestamp_demo;
ts | tstz
---------------------+------------------------
2016-06-22 19:10:25 | 2016-06-22 19:10:25-07
(1 row)
SET timezone = 'America/New_York';
SELECT
ts,
tstz
FROM
timestamp_demo;
Code language: SQL (Structured Query Language) (sql)
ts | tstz
---------------------+------------------------
2016-06-22 19:10:25 | 2016-06-22 22:10:25-04
(1 row)
SELECT NOW();
now()
function always returns the same timestamp within a single transaction. If you want to see the clock running while in a transaction, use the clock_timestamp()
function instead.
SELECT CURRENT_TIMESTAMP;
SELECT TIMEOFDAY();
timeofday
-------------------------------------
Wed Jun 22 20:51:12.632420 2016 PDT
SHOW TIMEZONE;
Code language: SQL (Structured Query Language) (sql)
TimeZone
---------------------
America/Los_Angeles
(1 row)
-- To convert 2016-06-01 00:00 to America/New_York timezone
SELECT timezone('America/New_York','2016-06-01 00:00');
Code language: SQL (Structured Query Language) (sql)
timezone
---------------------
2016-06-01 03:00:00
-- Note that we pass the timestamp as a string to the timezone() function, PostgreSQL casts it to timestamptz implicitly. It is better to -- cast a timestamp value to the timestamptz data type explicitly as the following statement:
SELECT timezone('America/New_York','2016-06-01 00:00'::timestamptz);
SET TIME ZONE ‘UTC+3’;
SELECT '2000-09-15 19:00+11:00'::TIMESTAMP, '2000-09-15 19:00+11:00'::TIMESTAMPTZ;
SELECT ‘2019-07-14 17:00:00.545454’::TIMESTAMP(0); – rounded up
select timestamptz '2017-01-08 04:05:06', -- handled by the timezone session parameter
timestamptz '2017-01-08 04:05:06+02'; -- input the time zone in the timestamp values directly
--- convert the stored timestamp to the client’s timezone at the database layer
SELECT '2000-01-01 00:00:00 +00:00'::timestamptz at time zone 'Europe/Rome' as "Rome's timestamp";
CURRENT_TIMESTAMP(precision)
If you omit the precision argument, the CURRENT_TIMESTAMP()
function will return a TIMESTAMP with a time zone that includes the full fractional seconds precision available.
The CURRENT_TIMESTAMP()
function returns a TIMESTAMP WITH TIME ZONE that represents the date and time at which the transaction started.Internally, the CURRENT_TIMESTAMP() is implemented with the NOW() function
CREATE TABLE note(
note_id serial PRIMARY KEY,
message varchar(255) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
TRANSACTION_TIMESTAMP()
function is equivalent to the CURRENT_TIMESTAMP
function.
TIME and TIMETZ
TIME
is still encoded with 8 bytes, representing microseconds since midnight.TIMETZ
is encoded with 12 bytes, with 8 bytes representing microseconds since midnight and 4 bytes for storing the time zone offset in seconds west of UTC
CURRENT_TIME
select ‘10:00’::time + ‘14 hours’::interval;
select ‘17:00:00.545454’::time(0), ‘17:00:00.545454+03’::timetz(0); -- parsing
Time Intervals
An interval describes a duration, like a month or two weeks, or even a millisecond:
set intervalstyle to postgres;
select interval '1 month',
interval '2 weeks',
2 * interval '1 week',
78389 * interval '1 ms';
interval │ interval │ ?column? │ ?column?
══════════╪══════════╪══════════╪══════════════
1 mon │ 14 days │ 14 days │ 00:01:18.389
(1 row)
set intervalstyle to postgres_verbose;
select interval '1 month',
interval '2 weeks',
2 * interval '1 week',
78389 * interval '1 ms';
interval │ interval │ ?column? │ ?column?
══════════╪═══════════╪═══════════╪═════════════════════
@ 1 mon │ @ 14 days │ @ 14 days │ @ 1 min 18.389 secs
(1 row)
select d::date as month,
(d + interval '1 month' - interval '1 day')::date as month_end,
(d + interval '1 month')::date as next_month,
(d + interval '1 month')::date - d::date as days
from generate_series(
date '2017-01-01',
date '2017-12-01',
interval '1 month'
)
as t(d);
When you attach an interval to a date or timestamp in PostgreSQL then the number of days in that interval adjusts to the specific calendar entry you’ve picked. Otherwise, an interval of a month is considered to be 30 days.
Interwal otrzymam jak odejmiemy dwa znaczniki czasowe od siebie
Select TIMESTAMP '2024-03-01 00:00:00' - TIMESTAMP '2024-02-01' as deys_in_febuaryn;
29 days
Odejmujac dwie daty otrzymamy liczbę dni
Select DATE '2024-03-01' - DATE '2024-02-01' as deys_in_febuaryn;
29