I have postgresql function that receive date variable, then I trunc day from time, but timezone anyway added to final query.
CREATE OR REPLACE FUNCTION public.request_user_track()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
BEGIN
IF TG_OP = 'INSERT' THEN
PERFORM pg_notify('user_log_added', '{"userID": ' || NEW."userID" || ',"time":"' || NEW.time || '"}');
INSERT INTO "UserTracks"("userID", "day", "requestedAt", "createdAt", "updatedAt")
VALUES(NEW."userID", date_trunc('day', NEW."time" AT TIME ZONE 'UTC'), NOW() + interval '1 second', NOW(), NOW())
ON CONFLICT("userID", "day") DO UPDATE SET "requestedAt" = EXCLUDED."requestedAt"
WHERE "UserTracks"."userID" = NEW."userID" AND "UserTracks".day = date_trunc('day', NEW."time" AT TIME ZONE 'UTC');
END IF;
RETURN NULL;
END;
$function$
;
I try to set timezone, but anyway in final query I have in db: 2019-12-30 03:00:00
Ok, given that the type of day is timestamptz in the db '2019-12-30 03:00:00' stored at MSK (+3) timezone, I believe the database is doing the right thing.
If you think about it, '2019-12-30 03:00:00 +03:00' is the same time as '2019-12-30 00:00:00 +00:00'. Now we just want the same timestamp to be stored at UTC timezone.
I have a hunch, try something like:
INSERT INTO "UserTracks"("userID", "day", ...)
VALUES(NEW."userID", date_trunc('day', NEW."time" AT TIME ZONE 'UTC') AT TIME ZONE 'UTC', ...)
It may be the case the result of date_trune() isn't kept at UTC timezone.
The other thing to note is that if this is deployed to a production server configured to run its OS and PostgreSQL in UTC (generally recommended) these issues won't exist.
You could change your session timezone or simply variable::timestamp or SELECT variable AT TIME ZONE 'desirable_timezone'. If you only want the date, then DATE(variable). It will depend on what you want to achieve, but all methods are valid for querying or modifing your table, with or without date_trunc.
SELECT date_trunc('day',date(now()))
Related
HIRE_DATE is in a 'DATE' column. The timestamp is local (Los Angeles); I would like to convert it to UTC.
I can't for the life of me fathom why the UTC output is mangled (Last 2 digits of YY is the DD; and vice-versa) -- and the time does not convert to UTC.
HIRE_DATE: 30/04/2019 12:00:00 AM
select from_tz(to_timestamp(HIRE_DATE,'DD-MM-YY HH24:MI:SS'), 'America/Los_Angeles') at time zone 'UTC' from TABLE
OUTPUT: 19/04/2030 12:00:00 AM
If HIRE_DATE is a DATE data type then you don't need TO_TIMESTAMP.
TO_TIMESTAMP is used to convert a string (i.e. VARCHAR2) into a TIMESTAMP value but you have a DATE value.
Just do
select from_tz(CAST(HIRE_DATE AS TIMESTAMP), 'America/Los_Angeles') at time zone 'UTC'
from TABLE
Actually I don't understand why FROM_TZ does not accept DATE values whereas almost any other date/timestamp related function accept either DATE or TIMESTAMP value as input.
Note, the default output display format of this query is defined by current user session NLS_TIMESTAMP_TZ_FORMAT setting. If you are not satisfied with the output format, either change NLS_TIMESTAMP_TZ_FORMAT setting by executing ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = '...' or use TO_CHAR function to set output format explicitly.
Instead of
... AT TIME ZONE 'UTC'
you can also use
SYS_EXTRACT_UTC(...)
The upper returns a TIMESTAMP WITH TIME ZONE value, the second one returns a TIMESTAMP value.
Would this do any good?
SQL> select from_tz(cast (sysdate as timestamp), 'UTC') result from dual;
RESULT
---------------------------------------------------------------------------
27.09.20 10:59:28,000000 UTC
Or, in your case
select from_tz(cast (hire_date as timestamp), 'UTC' from dual
No need to apply any format mask to hire_date as it is a DATE datatype (at least, that's what you said).
You use the word "convert" which can mean one of two things:
change the data type, which is what FROM_TZ does
change the value from one time zone to another, which FROM_TZ does not do.
You didn't give your expected output, so we may misunderstand.
To change the data type:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select from_tz(cast(dte as timestamp), 'America/Los_Angeles') from data
FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES')
30-APR-19 12.00.00.000000 PM AMERICA/LOS_ANGELES
To get the simultaneous datetime value in UTC:
with data(dte) as (
select date '2019-04-30' + interval '12' hour from dual
)
select cast(sys_extract_utc(from_tz(cast(dte as timestamp), 'America/Los_Angeles')) as date) from data
CAST(SYS_EXTRACT_UTC(FROM_TZ(CAST(DTEASTIMESTAMP),'AMERICA/LOS_ANGELES'))ASDATE)
2019-04-30 19:00:00
If I have date type variable
date_time date := sysdate; -- Suppose the timezone is EST.
Now, How I can convert the timezone of variable to UTC?
You can try this:
SELECT SYSTIMESTAMP at time zone 'UTC' FROM DUAL;
Its not very clear from your question what exactly you require but if I understood correctly you require time in UTC
SELECT CAST(sys_extract_utc(SYSTIMESTAMP) AS TIME) FROM DUAL;
I'm trying to convert the time which is timestamp with time zone means using now() or current_timestamp
SELECT TO_CHAR(now()::time, 'HH24:MI:SS')
current time it return is '06:06:17'
but it should return '18:06:17' but it won't return this
what might be the cause for this
The sql should be :-
SELECT TO_CHAR(now(), 'HH24:MI:SS')
How do i convert an oracle 'timestamp with time zone' variable in PL/SQL from one timezone to another?
The variable is declared like this:
v_date timestamp with time zone;
This statement returns '-04:00' on my server:
select dbtimezone from dual;
For our example, the data in the variable is in 'EDT' ('-04:00') and I want to convert to an arbitrary time zone, such as 'EET' ('+02:00') and store it in a differnt variable:
v_date2 timestamp with time zone;
You can convert from one time zone to another with at time zone. For example:
set serveroutput on
declare
v_ts1 timestamp with time zone;
v_ts2 timestamp with time zone;
begin
v_ts1 := to_timestamp_tz('2014-10-01 13:00:00 US/Eastern',
'YYYY-MM-DD HH24:MI:SS TZR');
v_ts2 := v_ts1 at time zone 'Europe/Athens';
dbms_output.put_line(v_ts1 || ' => ' ||
to_char(v_ts1, 'YYYY-MM-DD HH24:MI:SS TZH:TZM'));
dbms_output.put_line(v_ts2 || ' => ' ||
to_char(v_ts2, 'YYYY-MM-DD HH24:MI:SS TZH:TZM'));
end;
/
01-OCT-14 13.00.00.000000 US/EASTERN => 2014-10-01 13:00:00 -04:00
01-OCT-14 20.00.00.000000 EUROPE/ATHENS => 2014-10-01 20:00:00 +03:00
You can use the hour and minute offsets instead, but using zone and region names means you don't have to account for daylight savings yourself. Even using EET gives you an odd result as it's still summertime in eastern Europe as well (EEST rather than EET), so while you said you wanted a +02:00 time, it really ought to be +03:00 for most of the period that the eastern US is on EDT rather than EST. (Though the clocks change on different dates, so it isn't always aligned or obvious which to use).
Letting Oracle worry about that is much simpler and safer, and as Wernfried said, it's better to not use the abbreviated names to avoid ambiguity and confusion - and even errors.
Try to extract timestamp components using EXTRACT function or TO_CHAR function. Then set appropriate value using TO_TIMESTAMP_TZ function
After executing this SQL in oracle 10g:
SELECT SYSDATE, CURRENT_TIMESTAMP FROM DUAL
I receive this strange output:
What is cause of the difference in time?
The server time is equal of SYSDATE value
CURRENT_DATE and CURRENT_TIMESTAMP return the current date and time in the session time zone.
SYSDATE and SYSTIMESTAMP return the system date and time - that is, of the system on which the database resides.
If your client session isn't in the same timezone as the server the database is on (or says it isn't anyway, via your NLS settings), mixing the SYS* and CURRENT_* functions will return different values. They are all correct, they just represent different things. It looks like your server is (or thinks it is) in a +4:00 timezone, while your client session is in a +4:30 timezone.
You might also see small differences in the time if the clocks aren't synchronised, which doesn't seem to be an issue here.
SYSDATE, SYSTIMESTAMP returns the Database's date and timestamp, whereas current_date, current_timestamp returns the date and timestamp of the location from where you work.
For eg. working from India, I access a database located in Paris. at 4:00PM IST:
select sysdate,systimestamp from dual;
This returns me the date and Time of Paris:
RESULT
12-MAY-14 12-MAY-14 12.30.03.283502000 PM +02:00
select current_date,current_timestamp from dual;
This returns me the date and Time of India:
RESULT
12-MAY-14 12-MAY-14 04.00.03.283520000 PM ASIA/CALCUTTA
Please note the 3:30 time difference.
SYSDATE returns the system date, of the system on which the database resides
CURRENT_TIMESTAMP returns the current date and time in the session time zone, in a value of datatype TIMESTAMP WITH TIME ZONE
execute this comman
ALTER SESSION SET TIME_ZONE = '+3:0';
and it will provide you the same result.
SYSDATE provides date and time of a server.
CURRENT_DATE provides date and time of client.(i.e., your system)
CURRENT_TIMESTAMP provides data and timestamp of a clinet.
Note: SYSDATE - returns only the date, i.e., "yyyy-mm-dd" is not correct. SYSDATE returns the system date of the database server including hours, minutes, and seconds. For example:
SELECT SYSDATE FROM DUAL;
will return output similar to the following: 12/15/2017 12:42:39 PM
SYSDATE, systimestamp return datetime of server where database is installed. SYSDATE - returns only date, i.e., "yyyy-mm-dd". systimestamp returns date with time and zone, i.e., "yyyy-mm-dd hh:mm:ss:ms timezone"
now() returns datetime at the time statement execution, i.e., "yyyy-mm-dd hh:mm:ss"
CURRENT_DATE - "yyyy-mm-dd", CURRENT_TIME - "hh:mm:ss", CURRENT_TIMESTAMP - "yyyy-mm-dd hh:mm:ss timezone". These are related to a record insertion time.