postgres removes microseconds from now() - postgresql

My local postgres instance, version 12, removes the microseconds from my timestamp.
The column type is timestamp with out time zone.
My query is UPDATE trash SET updated_at = now() WHERE id = 164 and when I do select id, updated_at FROM trash WHERE id = 164 the microseconds are gone.
However, SELECT now() returns micrsoseconds.
Is there some configuration or something else that would help me understand why the microseconds aren't persisted?

I bet updated_at is of type timestamp(0) so that it discards fractional seconds.

Related

postgresql `at time zone` incorrect behaviour?

I have a simple postgresql table with the following data:
create table ti (
l text,
t timestamp without time zone
);
insert into ti(l, t) values ('now', now());
I do a select using at time zone, I expect UTC + 5.30 hours
select now(), t, t at time zone 'Asia/Kolkata' from ti;
But this is what I get:
now| t| timezone
2019-06-06T12:11:42.576388Z| 2019-06-06T11:50:48.178689Z| 2019-06-06T06:20:48.178689Z
It subtracted 5.30 hours instead of adding them.
Sqlfiddle here
now() returns a timestamp with time zone. The time zone info will be stripped off when it is cast to a timestamp without time zone when it is saved in your table, but the actual value saved in there will depend on the session time zone.
You can see this behavior pretty easily:
postgres=# begin;
BEGIN
postgres=# set time zone utc;
SET
postgres=# insert into test select now();
INSERT 0 1
postgres=# set time zone 'US/Eastern';
SET
postgres=# insert into test select now();
INSERT 0 1
postgres=# select * from test;
a
----------------------------
2019-06-06 12:46:10.475424
2019-06-06 08:46:10.475424
(2 rows)
A little more explanation after your comment. I think the issue you are having is with converting between timestamp and timestamptz. Timestamps are much less confusing if you stick with just timestamptz. Let's remove now() from the discussion, since that adds an additional layer of complexity because converting from the result of now() to a timestamp without time zone depends on the session time zone.
select '2019-06-06 12:00:00UTC'::timestamp with time zone,
('2019-06-06 12:00:00UTC'::timestamp with time zone) at time zone 'Asia/Kolkata';
timestamptz | timezone
------------------------+---------------------
2019-06-06 12:00:00+00 | 2019-06-06 17:30:00
I believe this is what you expect? We convert from a timestamp with time zone to a timestamp without time zone at a specific time zone.
What you are doing is similar to this, though:
select '2019-06-06 12:00:00UTC'::timestamp with time zone,
(('2019-06-06 12:00:00UTC'::timestamp with time zone)::timestamp without time zone) at time zone 'Asia/Kolkata';
timestamptz | timezone
------------------------+------------------------
2019-06-06 12:00:00+00 | 2019-06-06 06:30:00+00
(1 row)
I think you will find this much less confusing if you can store timestamp with time zone instead of timestamp without time zone.

Postgres timestamp with time zone saving with hour shift

I am trying to process input data putting timestamp when save it
tsSrc timestamp with time zone;
...
tsSrc := strTelegram.rte_data[ iPos ];-- this input data datetime
-- string e.g.'2015/12/13 21:35:26.000'
...
insert into telegram(
tld_id,
ddt_num, tld_src_timestamp,
tld_dst_timestamp, tld_year, tld_month,
tld_day, tld_hour, tld_min,
tld_sec, tld_data
) values(
uuId,
strTelegram.rte_type,
tsSrc,
strTelegram.rte_dst_timestamp,
extract(year from tsSrc), extract(month from tsSrc),
extract(day from tsSrc), extract(hour from tsSrc),
extract(minute from tsSrc), extract(second from tsSrc),
strTelegram.rte_data
);
But I have got unexpected result, tsSrc saved as 2015-12-13 20:35:26+03 i.e. has hour -1 shift, at the same time extract(hour from tsSrc) returns right value and saved as 21. What I am doing wrong?
Timezone is set as 'MSK-3' in postgresql.conf, select now() returns right datetime, postgresql 9.3.
You need to understand handling of timestamp (timestamp without time zone) and timestamptz (timestamp with time zone) and how each interacts with the timezone setting of your current session.
To explain the "difference" you observe we would need to know the exact table definition and the timezone setting of the session saving the row, as well as the timezone setting of the session displaying the row.
For example, if you take the timestamp literal '2015-12-13 21:35:26' (use ISO format to avoid additional complication with the input format!) and save it to a timestamptz column in a session with time zone offset +2 and later select the same row in a session with with time zone offset +3, then you get what you see:
SELECT '2015-12-13 21:35:26'::timestamp AT TIME ZONE '+2' AT TIME ZONE '+3';
Result:
'2015-12-13 20:35:26'
In other words: the timestamptz value '2015-12-13 20:35:26+03' is exactly the same (same point in time) as '2015-12-13 21:35:26+02', only the display has been adapted to your time zone setting. When you treat the timestamptz value according to the clock on the wall in your corner of the world (like you do with extract(hour from tsSrc)), you get different results depending where you are currently (the timezone setting of your session).
Detailed explanation:
Ignoring timezones altogether in Rails and PostgreSQL

INTERVAL vs TIMESTAMP (or similar)

I am wondering: Do I have any advantages when using INTERVAL instead of using to TIMESTAMP attributes from and to?
I am asking because I am having a table time_period that is supposed to be function as an abstract way of storing time interval information on a day and/or hour level:
CREATE TABLE time_period (
-- PRIMARY KEY
id BIGSERIAL PRIMARY KEY,
-- ATTRIBUTES
valid_for_days INT NOT NULL,
day_from TIMESTAMP WITH TIME ZONE NOT NULL,
day_to TIMESTAMP WITH TIME ZONE NOT NULL,
time_from TIMESTAMP WITH TIME ZONE NOT NULL,
time_to TIMESTAMP WITH TIME ZONE NOT NULL
);
Would I be better off using INTERVAL here?
The difference between two timestamps is an interval:
select now() - '2015-01-01';
?column?
--------------------------
370 days 18:45:20.312403
You only need two timestamps to have an interval not four.
If you store that as an interval you will lose the timestamp reference.

Postgres timestamp to unix time in milliseconds as a bigint

How can I get the following snippet to work in postgres:
ALTER TABLE mytable
ADD COLUMN create_time_utc bigint not null
DEFAULT (now() at time zone 'utc');
I want the new column create_time_utc to be the unix time in milliseconds (i.e number of milliseconds since Unix epoch January 1 1970).
I know I need to convert the postgres timestamp to a bigint, but I'm not sure how to do that.
extract(epoch
alter table mytable
add column create_time_utc bigint not null
default (extract(epoch from now()) * 1000);
http://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT

Using current time in UTC as default value in PostgreSQL

I have a column of the TIMESTAMP WITHOUT TIME ZONE type and would like to have that default to the current time in UTC. Getting the current time in UTC is easy:
postgres=# select now() at time zone 'utc';
timezone
----------------------------
2013-05-17 12:52:51.337466
(1 row)
As is using the current timestamp for a column:
postgres=# create temporary table test(id int, ts timestamp without time zone default current_timestamp);
CREATE TABLE
postgres=# insert into test values (1) returning ts;
ts
----------------------------
2013-05-17 14:54:33.072725
(1 row)
But that uses local time. Trying to force that to UTC results in a syntax error:
postgres=# create temporary table test(id int, ts timestamp without time zone default now() at time zone 'utc');
ERROR: syntax error at or near "at"
LINE 1: ...int, ts timestamp without time zone default now() at time zo...
A function is not even needed. Just put parentheses around the default expression:
create temporary table test(
id int,
ts timestamp without time zone default (now() at time zone 'utc')
);
Still another solution:
timezone('utc', now())
Wrap it in a function:
create function now_utc() returns timestamp as $$
select now() at time zone 'utc';
$$ language sql;
create temporary table test(
id int,
ts timestamp without time zone default now_utc()
);
What about
now()::timestamp
If your other timestamp are without time zone then this cast will yield the matching type "timestamp without time zone" for the current time.
I would like to read what others think about that option, though. I still don't trust in my understanding of this "with/without" time zone stuff.
EDIT:
Adding Michael Ekoka's comment here because it clarifies an important point:
Caveat. The question is about generating default timestamp in UTC for
a timestamp column that happens to not store the time zone (perhaps
because there's no need to store the time zone if you know that all
your timestamps share the same). What your solution does is to
generate a local timestamp (which for most people will not necessarily
be set to UTC) and store it as a naive timestamp (one that does not
specify its time zone).
These are 2 equivalent solutions:
(in the following code, you should substitute 'UTC' for zone and now() for timestamp)
timestamp AT TIME ZONE zone - SQL-standard-conforming
timezone(zone, timestamp) - arguably more readable
The function timezone(zone, timestamp) is equivalent to the SQL-conforming construct timestamp AT TIME ZONE zone.
Explanation:
zone can be specified either as a text string (e.g., 'UTC') or as an interval (e.g., INTERVAL '-08:00') - here is a list of all available time zones
timestamp can be any value of type timestamp
now() returns a value of type timestamp (just what we need) with your database's default time zone attached (e.g. 2018-11-11T12:07:22.3+05:00).
timezone('UTC', now()) turns our current time (of type timestamp with time zone) into the timezonless equivalent in UTC.
E.g., SELECT timestamp with time zone '2020-03-16 15:00:00-05' AT TIME ZONE 'UTC' will return 2020-03-16T20:00:00Z.
Docs: timezone()
Function already exists:
timezone('UTC'::text, now())