Default timestamp format and fractional seconds - postgresql

I'm trying to format the timestamps in my Postgres database to a certain format:
YYYY-MM-DD HH24:MI:SS
By doing:
update myTable set tds = to_char(tds, 'YYYY-MM-DD HH24:MI:SS')::timestamp;
I managed to set all the previously stored tds to this format. However, any newly added entry goes back to: YYYY-MM-DD HH24:MI:SS.MS since the default is set to now().
How do I change this so that newly added entries also have the format: YYYY-MM-DD HH24:MI:SS?

There is no format stored in a timestamp type. You can set its default to a timestamp truncated to the second at creation time
create table t (
tds timestamp default date_trunc('second', now())
)
Or alter the table
alter table t
alter column tds
set default date_trunc('second', now());
insert into t values (default);
INSERT 0 1
select * from t;
tds
---------------------
2014-03-11 19:24:11
If you just don't want to show the milliseconds part format the output
select to_char(now(), 'YYYY-MM-DD HH24:MI:SS');
to_char
---------------------
2014-03-11 19:39:40

The types timestamp or timestamptz optionally take a precision modifier p: timestamp(p).
To round to full seconds, set the default to:
now()::timestamp(0)
or:
now()::timestamptz(0)
Standard SQL functions CURRENT_TIMESTAMP (returns timestamptz) or LOCALTIMESTAMP (returns timestamp) allow the same precision modifier:
CURRENT_TIMESTAMP(0)
LOCALTIMESTAMP(0)
That's a bit shorter than calling date_trunc() - which truncates fractional seconds (may be what you really want!)
date_trunc('second', now())
Store timestamps as timestamptz (or timestamp), not as character type.
Finally, to make sure that ...
newly added entries also have the format: YYYY-MM-DD HH24:MI:SS
you could define your column as type timestamptz(0). This covers all values entered into that column, not just the default. But the rounding may introduce timestamps up to half a second in the future. If that can be an issue in any way, rather use date_trunc().
See #Clodoaldo's answer for instructions on to_char() and how to ALTER TABLE.
This related answer for in-depth information on timestamps and time zone handling:
Ignoring time zones altogether in Rails and PostgreSQL

Related

How to extract data from DWH on a certain date? Is there the special pattern for this case in Postgres SQL?

Usually we use EXTRACT (FROM YEAR date_column) = 2000 (let it be 2000 year). Also we can add EXTRACT (MONTH FROM date_column) = 1 (let it be January). Also we can extract a day - EXTRACT (DAY FROM date_column) = 5 (let it 5). But is it possible to use the pattern for this data? How does it look like in Postgres SQL
Say we have the table Shipment, the columns - date_payment, quantity, sum.
I'd like to get the table that content all shipments for 01.01.2020
How to query this table with data format 'YYYY-MM-DD', not using EXTRACT-function?
If the date column is a date type then:
SELECT * FROM some_table WHERE date_col = '2020-01-01';
If the column is timestamp or timestamptz then:
SELECT * FROM some_table WHERE date_trunc('day', date_col) = '2020-01-01'
Beware that with timestamptz time zones come into play when doing the date_trunc. From here date_trunc:
When the input value is of type timestamp with time zone, the truncation is performed with respect to a particular time zone; for example, truncation to day produces a value that is midnight in that zone. By default, truncation is done with respect to the current TimeZone setting, but the optional time_zone argument can be provided to specify a different time zone. The time zone name can be specified in any of the ways described in Section 8.5.3.
For a timestamp value per the above link:
A time zone cannot be specified when processing timestamp without time zone or interval inputs. These are always taken at face value.

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

How to alter table in Postgres to show Timestamp with Time Zone abbreviation (2004-10-19 10:23:54 EST)

I want to alter my table row from 2011-06-30 05:59:59+00 format into 2011-06-30 05:59:59 CDT format
As Tim told, postgres does not store TZ info. You can't change column this way. Unless you create function or view or something (which won't be changing the table anyway). What you do instead, you change timezone to see your needed:
timezone (string)
Sets the time zone for displaying and interpreting
time stamps. If not explicitly set, the server initializes this
variable to the time zone specified by its system environment. See
Section 8.5.3 for more information.
And use formatting to display TZ info... Like here:
b=# select now();
now
-----------------------------
2016-12-07 15:13:35.1369+00
(1 row)
b=# set timezone = EST;
SET
b=# select to_char(now(),'YYYY-MM-DD HH24:MI:SS TZ');
to_char
-------------------------
2016-12-07 10:13:55 EST
(1 row)

How do I convert timestamp and offset columns to a single timestamptz column?

Image I have a table containing the following two columns:
timestampwithouttimezone (of type TIMESTAMP WITHOUT TIME ZONE)
utcoffset (of type INTEGER)
I want to convert those two column to a single one of type TIMESTAMP WITH TIME ZONE. Can this be achieved using a ALTER TABLE ALTER COLUMN [column] SET DATE TYPE TIMESTAMP WITH TIME ZONE query and the additional USING clause?
Or do I need a separate UPDATE query that takes the offset and sets the timezone of the timestamps? If that's the case, what would that query be? I can't find any examples that show how to update the timezone using an integer.
You could do that like this, assuming the offset is in hours:
ALTER TABLE mytab
ALTER timestampwithouttimezone
TYPE timestamp with time zone
USING CAST (timestampwithouttimezone::text || ' '
|| to_char(utcoffset, 'S00FM')
AS timestamp with time zone),
DROP utcoffset;

Convert bigint data type to timestamp (and subsequently to date) in redshift

I need to convert the value stored in a bigint column to a date field. The first step of the conversion involves converting it to timestamp, and subsequently use the TRUNC method to convert this column to a date value.
However, my query is failing while converting the bigint value to timestamp.
The error that I'm getting is:-
Amazon Invalid operation: cannot cast type bigint to timestamp without time zone;
The query I'm trying for now is something like this:-
select ts::timestamp from events limit 1;
I was able to avoid the time zone error by using the method described in this thread: https://stackoverflow.com/a/36399361
My dates are based on epochs, and I was able to do the following:
SELECT
(TIMESTAMP 'epoch' + contract_start_date * INTERVAL '1 Second ')
FROM
table_name
SELECT TIMESTAMP 'epoch' + {column of bigint}/1000 * INTERVAL '1 second' as adate FROM tbl
If you are starting with a POSIX timestamp, and trying to get a timezone aware datetime value, you will need to supply a timezone - even if you later want to truncate the time part away. I'm not familiar with redshift, but perhaps there is a way to specify you mean UTC.