How to compare timestamp(6) columns with systimestamp in oracle - oracle

I want to compare the timestamp columns values with the systimestamp value.
My table contains two columns from_date and to_date with datatype of timestamp(6). I want to check something like this
systimestamp between from_date and thru_date
Upon checking systimestamp is returning value with timezone but from_date and thru_date columns values are without timezone
select systimestamp from dual; -- 11/19/2016 03:35:55.042420000 PM +08:00
And from_date & thru_date like 08/03/2015 06:09:56.941255000 AM
Please advise me how can I achieve this comparison?
Can I use LOCALTIMESTAMP instead of SYSTIMESTAMP? or I have to use from_tz function on from_date and to_date columns before comparison?

For a comparison Oracle has to perform an implicit cast. I just made a test and Oracle runs internally
systimestamp between CAST(from_date AS TIMESTAMP WITH TIME ZONE) and CAST(thru_date AS TIMESTAMP WITH TIME ZONE),
which is equivalent to
systimestamp between FROM_TZ(from_date, SESSIONTIMEZONE) and FROM_TZ(thru_date, SESSIONTIMEZONE)
In case your current SESSIONTIMEZONE is different from time zone of database server's operating system the query will return wrong result.
In order to get correct result you can use either of these expressions:
CAST(systimestamp AS TIMESTAMP) between from_date and thru_date
systimestamp between FROM_TZ(from_date, EXTRACT(TIMEZONE_REGION FROM SYSTIMESTAMP))
and FROM_TZ(thru_date, EXTRACT(TIMEZONE_REGION FROM SYSTIMESTAMP))
systimestamp between FROM_TZ(from_date, TO_CHAR(SYSTIMESTAMP, 'TZR'))
and FROM_TZ(thru_date, TO_CHAR(SYSTIMESTAMP, 'TZR'))
systimestamp between FROM_TZ(from_date, TO_CHAR(SYSTIMESTAMP, 'TZH:TZM'))
and FROM_TZ(thru_date, TO_CHAR(SYSTIMESTAMP, 'TZH:TZM'))
EXTRACT(TIMEZONE_REGION FROM SYSTIMESTAMP) may fail, depending on your server settings.
Note, do not use DBTIMEZONE instead of TO_CHAR(SYSTIMESTAMP, 'TZR'). DBTIMEZONE can be different from time zone of database server's operating system. Time zone of SYSTIMESTAMP is given in time zone of database server's operating system not DBTIMEZONE!

Related

Oracle server timezone using SQL query

I ran
select SYSDATE from dual;
Output:
SYSDATE |
-------------------|
2019-10-09 08:55:29|
Then I ran,
SELECT DBTIMEZONE FROM DUAL;
Output:
DBTIMEZONE|
----------|
+00:00 |
In the first output, time is in EST and 2nd output suggests timezone is UTC.
How do I check oracle server timezone via SQL query?
From the docs:
The database time zone [DBTIMEZONE] is relevant only for TIMESTAMP WITH LOCAL TIME ZONE columns. Oracle recommends that you set the database time zone to UTC (0:00)...
SYSDATE/SYSTIMESTAMP will return the time in the database server's OS timezone. Selecting a TIMESTAMP WITH LOCAL TIME ZONE datatype will return the time in your session's timezone (ie, SESSIONTIMEZONE).
select
CAST(systimestamp AS timestamp(0) with local time zone) as local_time,
systimestamp as server_time
from dual;
DBTIMEZONE is only used as the base timezone stored in TIMESTAMP WITH LOCAL TIME ZONE columns - which you never see, because when you select from one of those columns it gets translated into your session timezone.
See this similar question for a very detailed answer.
It is a common misunderstanding that SYSDATE or SYSTIMESTAMP are returned at DBTIMEZONE
SYSDATE and SYSTIMESTAMP are given in the time zone of database server's operating system. If you like to interrogate the time zone of database server's operating system run
SELECT TO_CHAR(SYSTIMESTAMP, 'tzr') FROM dual;
see also How to handle Day Light Saving in Oracle database

Comparing TIMESTAMP WITH TIME ZONE to DATE

I need to compare database generated dates (column values defaulting to SYSDATE) to hand written time stamps recorded with the time zone. This is the comparison I am trying:
where trunc(updated, 'mi') >= to_timestamp_tz('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR')
I assume that a character string converted to a TIMESTAMP WITH TIME ZONE should be comparable to a DATE. However, this only works if the database is located in my own time zone. Otherwise, I have to manually convert the external time stamp to the database time zone. For example, if I am in BST and the database is in EST, I have to write:
where trunc(updated, 'mi') >= to_timestamp_tz('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR')
Where 04:45 = 10:45 - 6, and 6 is the difference between BST and EST. This looks absolutely counter-intuitive as the original time stamp has been recorded in PST and is therefore entered as US/Pacific. Could anybody please explain why this conversion is needed? I would also appreciate if somebody suggests a better solution.
You can cast your DATE column to a TIMESTAMP WITH TIME ZONE value like this:
WHERE
FROM_TZ(CAST(TRUNC(updated, 'mi') AS TIMESTAMP),
(SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual)) >= to_timestamp_tz('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR')
but it works also the other way around, i.e. convert TIMESTAMP WITH TIME ZONE to DATE in database time zone:
WHERE
TRUNC(updated, 'mi') >=
CAST(TO_TIMESTAMP_TZ('2017-10-24 04:45 US/Pacific', 'YYYY-MM-DD HH24:mi TZR') AT TIME ZONE (SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual) AS DATE)
SYDATE is provided in the time zone of database server's operating system (NOT DBTIMEZONE) , thus you have to use (SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual) or provide hard-coded value if appropriate.
This approach fails if any users inserted/updated any updated using his current local time zone. In such cases the time zone information is lost and there is no way to recover it.
If you are running this query in any of oracle clients, You can also change the session setting by running
ALTER SESSION SET TIME_ZONE ='BST';
When you change the session time_zone all the date values coming from database column and time stamp values passed without time zone will be converted to BST.
hence it will ensure that the comparison is happening in common time zone

Issue with timezone in oracle

Below query is used in my code to get the timezone from database. (DB is in central time zone)
SELECT DBTIMEZONE FROM DUAL;
-05:00
When daylight saving is on (CDT), its expected result.
but when daylight saving ends (CST), my result should be GMT-06, but i am still getting GMT-05.
Googled and got below options :
SELECT TO_CHAR(SYSTIMESTAMP, 'TZR') FROM dual;
SELECT TZ_OFFSET('CST6CDT') FROM DUAL;
Will above queries run correctly accordingly to CST and CDT ??
DBTIMEZONE does not determine the time zone of SYSTIMESTAMP (or SYSDATE)
Time zone of SYSTIMESTAMP is the time zone of database server's operating system.
DBTIMEZONE is only relevant for data type TIMESTAMP WITH LOCAL TIME ZONE and defines the time zone in which those values are stored internaly. You cannot change DBTIMEZONE on your database if the database contains a table with a TIMESTAMP WITH LOCAL TIME ZONE column and the column contains data.

How to convert date object to timestamp in client?

for example
select to_timestamp(sysdate) from dual
return date object, not timestamp.
I try to change
NLS_TIMESTAMP_FORMAT='ss.ff'
but select return error.
If you are starting with sysdate then as #a_horse_with_no_name says you don't need to do a conversrion; use systimestamp or current_timestamp instead. (One is the server time, one is the client time, which will be the same unless your client is in a different timezone).
More generally though you can cast between data types:
select cast(date_field as timestamp) from your_table
You won't add any precision to the value though; the date already have a time down to second precision, even if that is midnight; and your timestamp will still have the fractional seconds part as zero.
If you just want to display your DATE as a string but show the time it already has then you need to specify the output format, e.g.
select to_char(sysdate, 'YYYY-MM-DD HH24:MI:SS') from dual

How to get UTC value for SYSDATE on Oracle

Probably a classic... Would you know a easy trick to retrieve an UTC value of SYSDATE on Oracle (best would be getting something working on the 8th version as well).
For now I've custom function :(
Cheers,
Stefan
You can use
SELECT SYS_EXTRACT_UTC(TIMESTAMP '2000-03-28 11:30:00.00 -02:00') FROM DUAL;
You may also need to change your timezone
ALTER SESSION SET TIME_ZONE = 'Europe/Berlin';
Or read it
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM dual;
select sys_extract_utc(systimestamp) from dual;
Won't work on Oracle 8, though.
Usually, I work with DATE columns, not the larger but more precise TIMESTAMP used by some answers.
The following will return the current UTC date as just that -- a DATE.
CAST(sys_extract_utc(SYSTIMESTAMP) AS DATE)
I often store dates like this, usually with the field name ending in _UTC to make it clear for the developer. This allows me to avoid the complexity of time zones until last-minute conversion by the user's client. Oracle can store time zone detail with some data types, but those types require more table space than DATE, and knowledge of the original time zone is not always required.
I'm using:
SELECT CAST(SYSTIMESTAMP AT TIME ZONE 'UTC' AS DATE) FROM DUAL;
It's working fine for me.
If you want a timestamp instead of just a date with sysdate, you can specify a timezone using systimestamp:
select systimestamp at time zone 'UTC' from dual
outputs: 29-AUG-17 06.51.14.781998000 PM UTC

Resources