Update only the time from a CURRENT_TIMESTAMP - sql

How can I update and change only the time-section of a CURRENT_TIMESTAMP in postgres SQL?
I have to INSERT INTO a TABLE a new VALUE with the CURRENT_TIMESTAMP to get the correct year, month and day. The Time needs always to be 10 PM.
I tried to find a function where I eventually just get a TIMESTAMP with the current Year,month, day and the default time of 00:00:00. Later I tried to DATEADD 22:00:00 Into it. Doesn't seem to work.

If the time part is the same for all rows without exception, I would not store it at all. Use a date column then turn that into a timestamp when selecting from the table:
select the_column + time '22:00:00' as the_column_adjusted
from the_table
Another alternative is to define a default value with a fixed time:
the_column timestamp default current_date + time '22:00:00'
This approach can also be used during an INSERT:
insert into the_table (the_column)
values (current_date + time '22:00:00');
To change existing rows, you can convert the timestamp to a date, then add the desired time back:
update the_table
set the_column = the_column::date + time '22:00:00'
where ...

You can convert current_timestamp, which is of type "timestamptz" (short for "timestamp with time zone"), to a "date", then back to "timestamp with time zone", which will make it 00:00 at current timezone used by connection, and then add 22h:
=> select current_timestamp::date::timestamptz+'22h'::interval;
2022-11-05 22:00:00+01
You can simplify this with just using current_date:
=> select current_date::timestamptz+'22h'::interval;
2022-11-05 22:00:00+01
If you want to make it independent from current connection timezone, and just use UTC date (or any other time zone you need), you can use:
=> select ((current_timestamp at time zone 'UTC')::date::timestamp+'22h'::interval)::timestamptz;
2022-11-05 22:00:00+01
But, if hour is not important, then "date" type would be better and more efficient to store than "timestamp with time zone".
And never ever use "timestamp" type (short for "timestamp without timezone") for anything.

Related

Can't extract timezone_hour from postgres timestamp

ERROR: timestamp units "timezone" not supported
That's the error I get for all timezone fields.
Here's a minimal query you can run:
select extract(timezone_hour from now()::timestamptz at time zone 'US/Eastern');
What I want is the utc offset in hours. So this should return -4.
The requirement is that I use a dynamic time zone in the query. So I have a table of "facilities" with time zone strings, and I need to get the current time for each one.
So my end query should look something like this:
SELECT
EXTRACT(timezone_hour from now() with time zone timezone) # timezone is the name of the field
FROM facilities;
I thought I had it for a second with this, but this is giving me my current offset, not the offset of the tz I'm passing:
select
extract(timezone_hour from (select now()::timestamp at time zone 'US/Eastern'))
date_part
-----------
-7
I ended up getting this to work with creating two timestamps, one at utc and one at the desired time zone, but I'll leave this open just in case there's a better solution than my current one:
select
extract(hour from (
select (
select now() at time zone 'US/Eastern') - (select now() at time zone 'UTC')));
date_part
-----------
-4

NUMTODSINTERVAL in Redshift. Convert a number to hours

My goal is to offset timestamps in table Date_times to reflect local timezones. I have a Timezone_lookup table that I use for that, which has a column utc_convert and its values are (2, -1, 5, etc.) depending on the timezone.
I used to use NUMTODSINTERVAL in Oracle to be able to convert the utc_convert values to hours so I can add/subtract from the datetimes in the Date_times table.
For Redshift I found INTERVAL, but that's only hardcoding the offset with a specific number.
I also tried:
SELECT CAST(utc as TIME)
FROM(
SELECT *
,to_char(cast(utc_convert as int)||':00:00', 'HH24') as utc
from Timezon_lookup
)
But this doesn't work as some number in the utc_convert column have negative values. Any ideas?
Have you tried multiplying the offset by an interval:
select current_timestamp + utc_convert * interval '1 hour'
In Oracle, you can use the time zone of the user's session (which means you do not need to maintain a table of time zone look-ups or compensate for daylight savings time).
SELECT FROM_TZ( your_timestamp_column, 'UTC' ) AT LOCAL
FROM Date_times
SQLFIDDLE
In RedShift you should be able to use the CONVERT_TIMEZONE( ['source_timezone',] 'target_timezone', 'timestamp') function rather adding a number of intervals. This would allow you to specify the target_timezone as a numeric offset from UTC or as a time zone name (which would automatically compensate for DST).

In Postgres, how do you extract the month (according to specific timezone) from a given TIMESTAMP WITH TIME ZONE column?

I have a column called login_timestamp, which is of type TIMESTAMP WITH TIME ZONE.
To retrieve the month for this timestamp, I would do: EXTRACT(MONTH FROM login_timestamp).
However, I would like to retrieve the month for a specific time zone (in my case, Pakistan), but can't figure out how to do that.
Documentation for this is under Date/Time Functions and Operators. Search that page for "at time zone".
select extract(month from login_timestamp at time zone 'Asia/Karachi');
You can change the time zone for a single session or for a single transaction with set session... or set local.... For example, this changes the time zone for the current session.
set session time zone 'Asia/Karachi';
Use the AT TIME ZONE construct:
SELECT EXTRACT(MONTH FROM login_timestamp AT TIME ZONE '-5');
-5 is the constant offset for Pakistan.
Details:
Ignoring timezones altogether in Rails and PostgreSQL
Try applying AT TIME ZONE. Demo
select extract(month from cast ('2017-07-01 01:00+03' as TIMESTAMP WITH TIME ZONE) AT TIME ZONE '+08') as monthNo
returns
monthno
1 6

How to get the date and time from timestamp in PostgreSQL select query?

How to get the date and time only up to minutes, not seconds, from timestamp in PostgreSQL. I need date as well as time.
For example:
2000-12-16 12:21:13-05
From this I need
2000-12-16 12:21 (no seconds and milliseconds only date and time in hours and minutes)
From a timestamp with time zone field, say update_time, how do I get date as well as time like above using PostgreSQL select query.
Please help me.
There are plenty of date-time functions available with postgresql:
See the list here
http://www.postgresql.org/docs/9.1/static/functions-datetime.html
e.g.
SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 16
For formatting you can use these:
http://www.postgresql.org/docs/9.1/static/functions-formatting.html
e.g.
select to_char(current_timestamp, 'YYYY-MM-DD HH24:MI') ...
To get the date from a timestamp (or timestamptz) a simple cast is fastest:
SELECT now()::date
You get the date according to your local time zone either way.
If you want text in a certain format, go with to_char() like #davek provided.
If you want to truncate (round down) the value of a timestamp to a unit of time, use date_trunc():
SELECT date_trunc('minute', now());
This should be enough:
select now()::date, now()::time
, pg_typeof(now()), pg_typeof(now()::date), pg_typeof(now()::time)

in postgres, can you set the default formatting for a timestamp, by session or globally?

In Postgres, is it possible to change the default format mask for a timestamp?
right now comes back as
2012-01-03 20:27:53.611489
I would like resolution to minute like this:
2012-01-03 20:27
I know I can do this on individual columns with to_char() as or stripped down with a substr() by the receiving app, but having it formatted correctly initially would save a lot of work and reduce a lot of errors.
In PostgreSQL, The formatting of timestamps is independent of storage. One answer is to use to_char and format the timestamp to whatever format you need at the moment you need it, like this:
select to_char(current_timestamp, 'yyyy-MM-dd HH24:MI:SS.MS');
select to_timestamp('2012-10-11 12:13:14.123',
'yyyy-MM-dd HH24:MI:SS.MS')::timestamp;
But if you must set the default formatting:
Change the postgresql timestamp format globally:
Take a look at your timezone, run this as an sql query:
show timezone
Result: "US/Eastern"
So when you are printing out current_timestamp, you see this:
select current_timestamp
Result: 2012-10-23 20:58:35.422282-04
The -04 at the end is your time zone relative to UTC. You can change your timezone with:
set timezone = 'US/Pacific'
Then:
select current_timestamp
Result: 2012-10-23 18:00:38.773296-07
So notice the -07 there, that means we Pacific is 7 hours away from UTC. How do I make that unsightly timezone go away? One way is just to make a table, it defaults to a timestamp without timezone:
CREATE TABLE worse_than_fail_table
(
mykey INT unique not null,
fail_date TIMESTAMP not null
);
Then if you add a timestamp to that table and select from it
select fail_date from worse_than_fail_table
Result: 2012-10-23 21:09:39.335146
yay, no timezone on the end. But you want more control over how the timestamp shows up by default! You could do something like this:
CREATE TABLE moo (
key int PRIMARY KEY,
boo text NOT NULL DEFAULT TO_CHAR(CURRENT_TIMESTAMP,'YYYYMM')
);
It's a text field which gives you more control over how it shows up by default when you do a select somecolumns from sometable. Notice you can cast a string to timestamp:
select '2012-10-11 12:13:14.56789'::timestamp
Result: 2012-10-11 12:13:14.56789
You could cast a current_timestamp to timestamp which removes the timezone:
select current_timestamp::timestamp
Result: 2012-10-23 21:18:05.107047
You can get rid of the timezone like this:
select current_timestamp at time zone 'UTC'
Result: "2012-10-24 01:40:10.543251"
But if you really want the timezone back you can do this:
select current_timestamp::timestamp with time zone
Result: 2012-10-23 21:20:21.256478-04
You can yank out what you want with extract:
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 20
And this monstrosity:
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'EST';
Result: 2001-02-16 20:38:40
In postgres, you can change the default format mask for datetimes - using the set datestyle option; the available options can be found here (see 8.5.2. Date/Time Output).
Unfortunately, all the available options include the number of seconds - you will therefore need to reformat them either in the query or the application code (if applicable).
to_char() is used to create a string literal. If you want a different timestamp value, use date_trunc():
date_trunc('minute', now())
For converting literal input, use to_timestamp():
to_timestamp('2012-01-03 20:27:53.611489', 'YYYY-MM-DD HH24:MI')
This returns timestamptz. Cast to timestamp [without time zone] by appending ::timestamp (which assumes your current timezone setting), or with the AT TIME ZONE construct to define a time zone explicitly.
To my knowledge, there is no setting in PostgreSQL that would trim seconds from timestamp literals by default.