postgresql ignore milliseconds from timestamp when doing a select statement - postgresql

I have TableA and it has a field of
time_captured | timestamp without time zone | default now()
It is being used to record when data was inserted into the table. However, I am trying to do a select and ignore milliseconds.
So instead of having
2015-07-11 18:06:33.690498
2015-07-12 13:36:21.274509
2015-07-12 13:36:24.222577
2015-07-12 13:36:26.515593
I would like to have
2015-07-11 18:06:33
2015-07-12 13:36:21
2015-07-12 13:36:24
2015-07-12 13:36:26
Having the microseconds in the table is needed but what I do not need is for the output to show the microseconds.
How can I do this ?
The closest I have come is by using the following but I am not able to figure out how to pull the full date with the time as shown above.
SELECT EXTRACT(YEAR FROM time_captured AT TIME ZONE 'UTC') FROM server_perf; date_part
Thank you :)

You can use the date_trunc function to achieve this:
select date_trunc('second', time_captured) from server_perf;
see http://www.postgresql.org/docs/9.1/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC for more on this.

Related

Having a problem finding those records between yesterday and today based on a UTC column value using PostgreSQL

Using PostgreSQL and trying to query a table that contains a UTC column. The UTC column is a column without the timezone as I understand it from the developer. Example in my DB for a record is (2021-08-26 13:59:26.867578). And I have to search for records that are between yesterday's date and today's date. When I tried the SQL statement below I get this error:
[42883] ERROR: operator does not exist: timestamp without time zone - integer Hint: No operator matches the given name and argument types. You might need to add explicit type casts. Position: 63
Here is my SQL statement for PostgreSQL:
SELECT omd.*
FROM "OCRMetaDatas" omd
WHERE (omd."ScannedAt")-5 BETWEEN Now()-1 and now()
ORDER BY omd."ScannedAt" desc;
Any help/direction would be appreciated. Thanks.
You can't operate integer with datetimes. Here you are trying to do that twice:
(omd."ScannedAt")-5
and
Now()-1
You should use INTERVAL with datetime there, such as:
SELECT omd.*
FROM "OCRMetaDatas" omd
WHERE (omd."ScannedAt")- '5 days'::INTERVAL BETWEEN Now()- '1 day'::INTERVAL and now()
ORDER BY omd."ScannedAt" desc;
As illustration of how to use at time zone:
--My TimeZone
show TimeZone;
TimeZone
------------
US/Pacific
select '2021-08-26 13:59:26.867578'::timestamp;
timestamp
----------------------------
2021-08-26 13:59:26.867578
select '2021-08-26 13:59:26.867578'::timestamp at time zone 'UTC';
timezone
-------------------------------
2021-08-26 06:59:26.867578-07
select now();
now
-------------------------------
2021-08-26 09:23:57.818477-07
at time zone will normalize the timestamps to the same time zone.

Need help to identify the actual date time format

I have been struggling since few days to identify correct format for sample input date:
2020-01-30 14:39:25.022000 +00:00:00
Background :
I am working on data migration with postgres. And, have identified that in DB, the datetime related fields like 'modifiedAt' have datatype as varchar, which is bit weird. These records have values in above mentioned format.
I have fixed it in new postgres DB instance with datatype as timestamp. After migrating data, these fields are showing datetime in following format:
2020-01-30 14:39:25
How can I format above date to give output in this dateformat 2020-01-30 14:39:25.022000 +00:00:00?
Any help will be appreciated.
First you want to use timestamptz not timestamp. timestamptz does not actually store the time zone, it just makes the value time zone aware. For more information on this see:
Time Stamps 8.5.1.3. Time Stamps.
Second it looks like you did something like timestamp(0) which reduced the precision to whole seconds. If you leave the precision alone you get:
select '2020-01-30 14:39:25.022000 +00:00:00'::timestamptz;
timestamptz
-----------------------------
01/30/2020 06:39:25.022 PST
-- I am in PST so the value gets rotated to that time zone for display.
-- If you want something closer to you desired output, then:
select to_char('2020-01-30 14:39:25.022000 +00:00:00'::timestamptz AT TIME ZONE 'UTC', 'YYYY-MM-DD HH24:MI:SS.USOF');
to_char
-------------------------------
2020-01-30 14:39:25.022000+00
While your timestamp strings do appear to have a time zone component, it is +00, which is the default for timestamps. So, you might be able to just use TO_TIMESTAMP here with an appropriate format mask covering microseconds:
WITH yourTable AS (
SELECT '2020-01-30 14:39:25.022123 +00:00:00'::text AS ts
)
SELECT TO_TIMESTAMP(LEFT(ts, 26), 'YYYY-MM-DD HH24:MI:SS.US')
FROM yourTable;
Demo
The output value from the demo above is 2020-01-30 14:39:25.022123+00

date_trunc at time zone with original timestamptz

I have a single timestamptz that I want to date_trunc so it removes the hours:
2019-01-01T17:43-03 => 2019-01-01T00:00-03.
However, because date_trunc removes the timezone, I need to do it like this:
date_trunc('day', '2019-01-01T17:43-03'::timestamptz) at time zone '-03'
However, I do not want to hardcode the time zone, since the query is run with timestamptz in many different timezones (these are input to the query and not stored). So I want the timezone to be extracted from the original timestamp. I tried to do something like this, but it does not work:
date_trunc('day', '2019-01-01T17:43-03'::timestamptz) at time zone EXTRACT(...)
Related, I am trying to extract the timezone from a timestamptz, but just getting 0.
SELECT EXTRACT(timezone FROM TIMESTAMP WITH TIME ZONE '2019-01-01T00:00+03')
0
Can anybody help me with this?
I believe you may have a misconception about how timestamps and timezones are stored in PostgreSQL (because you seem to expect the -03 to be preserved when calling date_trunc and that you "want the timezone to be extracted from the original timestamp"). According to the documentation:
When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as local time in that zone. To see the time in another time zone, either change timezone or use the AT TIME ZONE construct (see Section 9.9.3).
Therefore, the statement that "different clients [that] have timestampts in many different timezones," while true, are all translated to UTC for storage, and then displayed in your local timezone (or the timezone you specify) for output. As such, calling date_trunc() will essentially truncate the UTC timestamp, and if you want it displayed in a specific timezone, you will need to add the AT TIME ZONE clause.
UPDATE: An example is here:
edb=# select date_trunc('day', '2019-01-01T17:43-03'::timestamptz) ;
date_trunc
------------------------
2019-01-01 00:00:00+00
(1 row)
edb=# set timezone to 'US/Pacific';
SET
edb=# select date_trunc('day', '2019-01-01T17:43-03'::timestamptz) ;
date_trunc
------------------------
2019-01-01 00:00:00-08
(1 row)
As you can see, date_trunc will append the timezone that I defineā€”it is not omitted.

Postgresql How extract date

I need get only the date from now() at my time zone, I have this query:
SELECT now() AT TIME ZONE 'America/Santiago'
And I'm getting something like this "2015-06-08 23:59:34.142569"
but I need extract only the date, how can I get it?
Thanks.
If you want the server's date,
SELECT current_date;
If you need the date for any timestamp, eg the one you've gotten into your timezone, use date().
SELECT date(now() AT TIME ZONE 'America/Santiago');
Docs: http://www.postgresql.org/docs/current/static/functions-datetime.html
For postgres you want
select current_date;
if you need to extract any of those fields out of the returned value you can use extract
EXTRACT (field FROM source)

timezone aware date_trunc function

The following query
SELECT the_date FROM date_trunc('day', timestamp with time zone
'2001-01-1 00:00:00+0100') as the_date
results to
the_date
2000-12-31 00:00
Is there a way to tell date_trunc to do day/month/year conversions based on the timezone it is feeded with?
The expected output would be: 2001-01-1 00:00+0100
You need to specify at which time zone you want it to show
select
date_trunc(
'day',
timestamp with time zone '2001-01-1 00:00:00+0100' at time zone '-02'
) as the_date;
the_date
---------------------
2001-01-01 00:00:00
AT TIME ZONE
While the marked answer might be correct for the OP's weird circumstances it is more likely incorrect for others. You need to convert the timestamp returned by date_trunc to the proper timezone.
select
date_trunc(
'day',
some_timestamp at time zone users_timezone
) at time zone users_timezone as the_date;
The important thing to understand is date_trunc returns a timestamp with no timezone attached to it. You need to convert the timestamp to the proper timezone because the database client or whatever downstream might have a different timezone.
#Adam's answer is definitely more helpful. Although I think we can improve on it again because if we're truncating a Timestamp to a single day (or week/month/etc), then we want to make sure that we're dealing with a Date object, not a Timestamp. Otherwise we may give other pieces of code the impression that something just actually happened to occur at midnight (or potentially some other misleading time of day).
So I would use:
SELECT date_trunc('day', some_timestamp AT TIME ZONE users_timezone)::date AS the_date;
which casts the result to a Date, rather than Timestamp.
The result will be something like:
the_date
------------
2019-09-14
instead of the more misleading result of:
the_date
---------------------
2019-09-14 00:00:00