How to change a timestamp with timezone to date (YYYY) - postgresql

I'm trying to change an entire columns format into a smaller date format. I'm currently using PostgreSQL and need to change it from timestamp with timezone to an easier format, preferably one that just displays the year? How can I get this done?
Ive tried using to_char functions as well as date_parse to no avail. Im still very new to this so its stumping me at this point, any help is much appreciated
Wed Dec 31 2008 19:00:00 GMT -0500 (Eastern Time Zone) is the current format.
I just want to be able to turn that into the year, so 2008

Seeing that you're dealing with text, it's best to convert it to an actual timestamptz first, using to_timestamp(). Then you can alter the column, casting it in place: online demo
create table your_table(invoicedate text);
insert into your_table values
('Wed Dec 31 2008 19:00:00 GMT -0500 (Eastern Time Zone)');
alter table your_table
alter column invoicedate
type timestamptz using
(to_timestamp(invoicedate,'Dy Mon DD YYYY HH24:MI:SS AAA TZHTZM'));
alter table your_table
add column invoiceyear smallint;
update your_table set invoiceyear=extract(year from invoicedate);
Already mentioned extract() can get you the year out of a timestamptz.
Keep in mind that PostgreSQL will consume the timestamps and keep them internally as UTC. This means that if you want to process invoices differently based on their timezone of origin, you'll have to save that origin information in a separate column. Right now, extracting a year from that timestamp will give you 2009 instead of 2008, because that time in EST corresponds to 2009 in UTC. To get it as 2008, you'll have to read it as invoicedate at time zone 'EST'

Related

How to manipulate column data in postgres

I need to manipulate column data in postgres
When I run the query-
SELECT t.date::varchar
FROM generate_series(timestamp '2020-02-27'
, timestamp '2020-03-01'
, interval '1 day') AS t(date);
it returns -
2020-02-27 00:00:00
2020-02-28 00:00:00
2020-02-29 00:00:00
2020-03-01 00:00:00
I want -
20200227
20200228
20200229
20200301
Removed '-' and truncated from end.
Can someone guide
If you don't specifically need some features of a varchar, by default use text instead.
You don't need to cast every time - generate_series() will do that automatically once it detects your step is an interval. That's unless you specifically want the generate_series(timestamp,timestamp,inteval) variant, not generate_series(timestamptz,timestamptz,inteval).
If you cast to be explicit, cast your dates as date. Regardless of whether you leave it as text literal or make them actual dates, PostgreSQL will have to cast them to match the function definition.
If you're planning to group things by a text-based date or do that to truncate timestamps, consider date_bin() and date_trunc() as well as simply holding things as a native date type. It'll take less space, run faster and enable native date-specific functions.
Make sure you're using to_char() to its full potential - it can save a lot of formatting later.
SELECT to_char(t.date,'YYYYMMDD') as date
FROM generate_series('2020-02-27'
, '2020-03-01'
, interval '1 day') AS t(date);
-- date
------------
-- 20200227
-- 20200228
-- 20200229
-- 20200301

Convert a postgres timestamp with no timezone column to a date

Given a postgres table with a column that is a timestamp without time zone
select "columnWithoutTimeZone" from my_table
Which results in:
columnWithoutTimeZone
Jun 11, 2022, 1:15:06 AM
Jun 11, 2022, 1:15:06 AM
How can the date component of timestamp be extracted?
I tried
select to_date("columnWithoutTimeZone") from my_table
But this produced an error:
ERROR: function to_date(timestamp without time zone) does not exist
There is a similar stack question, but that deals with timezone conversions. I am simply trying to extract the Jun 11, 2022 that is presently represented in the column.
Thank you in advance for your consideration and response.
Does this work for you?
select "columnWithoutTimeZone"::date from my_table

Oracle giving different times after changing timezone and converting to char

I have trying to convert the UTC time to local time in Oracle Developer as per query below. I needed it in a particular format after conversion but after conversion to character the time comes out to be completely different. Can anyone tell me what am I doing wrong here please.
select e.encntr_id
,to_char(e.reg_dt_tm,'YYYY-MM-DD hh24:mm') as reg_dt_tm
,to_char(from_tz (cast(e.reg_dt_tm as timestamp),'UTC') at time zone
'Australia/Sydney','YYYY-MM-DD hh24:mm') as aest_reg_char
,from_tz (cast(e.reg_dt_tm as timestamp),'UTC') at time zone 'Australia/Sydney' as aest_reg
from encounter e
where e.ENCNTR_ID in(123)
encntr_id reg_dt_tm aest_reg_char aest_reg
123 2022-03-03 05:03 2022-03-03 16:03 03/MAR/22 04:51:12.000000000 PM AUSTRALIA/SYDNEY
Use TO_CHAR:
TO_CHAR(
from_tz (cast(e.reg_dt_tm as timestamp),'UTC') at time zone 'Australia/Sydney',
'YYYY-MM-DD hh24:mm:ss.ff TZR'
)
Or change the default TIMESTAMP_TZ format in SQL Developer:
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF TZR';
and then run the query.
db<>fiddle here

Why date time different 1 hour when retrieve timestamp data of postgresql from rails

I have a problem that is
I migrate database table from rails.
In the tables columns timestamps with timezone is also include.
When I insert data into database, timestamp columns save current time as (eg. 2012-08-09 12:00:00 UTC+6:30)
I think it means 2012-08-09 18:30.
but when i retrieve this data from rails 3.2.6 it display as 2012-08-09 5:30
Why it display as 1 hour different from actual time. Is there any idea? please
At a guess, you're storing it with one timezone setting and retrieving it with a different one.
For example, if Rails thinks you're in UTC+6:30 but PostgreSQL thinks you're in UTC+5:30, and if Rails sends dates to Pg timezone qualified but reads them from Pg with the assumption that they're in local time, this would happen. It's safest to make sure your database driver always reads and writes dates timezone-qualified.
Given the one hour gap, I'm wondering if daylight savings is involved, but it could also just be that your timezone is off by one hour.
regress=# create table test ( x timestamp with time zone );
CREATE TABLE
regress=# insert into test (x) values ('2012-08-09 12:00:00 UTC+6:30');
INSERT 0 1
regress=# SET TIMEZONE = '-5:30';
SET
regress=# select * from test;
x
---------------------------
2012-08-10 00:00:00+05:30
(1 row)
regress=# SET TIMEZONE = '-6:30';
SET
regress=# select * from test;
x
---------------------------
2012-08-10 01:00:00+06:30
(1 row)
Alternately, maybe your database is in time zone '-1:00' and your application is stripping off the time zone when it reads the date, so the date appears to be off by one hour. It's hard to say with the available information.
To really help you it would be necessary for you to show:
The code that inserts the date
The INSERT statement that really inserts the date, captured by enabling log_statement = 'all' in postgresql.conf, along with any SET TIMEZONE statements that session ran before the INSERT.
The result of SELECTing that column from the database after a SET TIMEZONE = 'UTC'
and the code that reads the date
the time
2012-08-09 12:00:00 UTC+6:30
is in the timezone UTC+6:30(GMT+6:30) when you save it.
When you retrieve it you get the time in GMT timezone.
Both are same timings as 2012-08-09 5:30 GMT = 12:00:00 GMT+6:30.
EDIT:
This is for #CraigRinger...
Let's say...
UTC is London and UTC + 6:30 is Rangoon so...
6:30 at Rangoon = 12:00 at London
Subtracting 6:30 from both
12:00 at Rangoon = 5:30 at London
12:00 UTC+6:30 = 5:30 UTC
Data stored in UTC+6:30 = Data retrieved in UTC

PostgreSQL - how to render date in different time zone?

My server is in Central Time. I would like to render timestamps using Eastern time.
For instance, I would like to render 2012-05-29 15:00:00 as 2012-05-29 16:00:00 EDT.
How can I achieve it?
to_char('2012-05-29 15:00:00'::timestamptz at time zone 'EST5EDT', 'YYYY-MM-DD HH24:MI:SS TZ') gives 2012-05-29 16:00:00 (no zone).
to_char('2012-05-29 15:00:00'::timestamp at time zone 'EST5EDT', 'YYYY-MM-DD HH24:MI:SS TZ') gives 2012-05-29 14:00:00 CDT (wrong).
This one works, but it's so ridiculously complicated there must be an easier way: replace(replace(to_char(('2012-05-29 15:00:00'::timestamptz at time zone 'EST5EDT')::timestamptz, 'YYYY-MM-DD HH24:MI:SS TZ'), 'CST', 'EST'), 'CDT', 'EDT')
The key is to switch the local timezone to the desired display timezone, for the duration of the transaction:
begin;
set local timezone to 'EST5EDT';
select to_char('2012-05-29 15:00:00'::timestamp at time zone 'CDT',
'YYYY-MM-DD HH24:MI:SS TZ');
end;
The result is:
2012-05-29 16:00:00 EDT
Note that with set [local] timezone it is required to use full time zone names instead of abbreviations (for instance, CST would not work). Look up in the pg_timezone_names view for valid choices.
To use that method in a context similar to a to_char() call, I believe this function does the job:
CREATE FUNCTION display_in_other_tz(
in_t timestamptz,
in_tzname text,
in_fmt text) RETURNS text
AS $$
DECLARE
v text;
save_tz text;
BEGIN
SHOW timezone into save_tz;
EXECUTE 'SET local timezone to ' || quote_literal(in_tzname);
SELECT to_char(in_t, in_fmt) INTO v;
EXECUTE 'SET local timezone to ' || quote_literal(save_tz);
RETURN v;
END;
$$ language plpgsql;
In fact, PG knows it all - to_char(x, 'TZ') differentiates CST from
CDT correctly, and at time zone EST5EDT respects DST as well.
When dealing with a timestamp Postgres knows:
The setting of the GUC timezone.
The data type.
The value, which is the same count of seconds since '1970-1-1 0:0 UTC' for timestamp and timestamptz. (Or, to be precise: UT1.)
Details about other time zones in your date/time configuration files
When interpreting input, Postgres uses information about the provided time zone.
When rendering a timestamp value, Postgres uses the current timezone setting, but time zone offset, abbreviation or name are only used to compute the correct value on input. They are not saved. It is impossible to extract that information later. More details in this related answer:
Your "correct" example is almost correct. TZ of to_char() returns 'CDT' for timestamps that fall in the daylight saving periods of Central Time and 'CST' else. Eastern Time (EST /EDT) switches daylight saving hours at the same local time - I quote Wikipedia:
The time is adjusted at 2:00 AM local time.
The two time zones are out of sync during two hours per year. Of course, this can never affect a timestamp at 15:00 or 16:00, only around 02:00.
A fully correct solution - much like what #Daniel already posted, slightly simplified:
BEGIN;
SET LOCAL timezone to 'EST5EDT';
SELECT to_char('2012-05-29 15:00 CST6CDT'::timestamptz
, 'YYYY-MM-DD HH24:MI:SS TZ')
RESET timezone; -- only if more commands follow in this transactions
END;
The effects of SET LOCAL last only till the end of the current transaction.
The manual about SET LOCAL.