I have a requirement to check tasks in progress using Scheduled start time (PST) and scheduled end time(PST) .Datatype is timestamp with timezone for Scheduled start time and scheduled end time .
sysdate ( UTC )should be in between the start and end date to confirm tasks in progress
JIRA_KEY sch_start_time sch_end_time
1 11/04/2016 1:00:00 AM PST 14/04/2016 2:00:00 PM PST
2 12/04/2016 2:00:00 AM PST 12/04/2016 5:00:00 AM PST
3 12/04/2016 2:00:00 AM PST 14/04/2016 5:00:00 AM PST
Expected Output -
JIRA_KEY sch_start_time sch_end_time
1 11/APR/2016 1:00:00 AM PST 14/APR/2016 2:00:00 PM PST
3 12/APR/2016 2:00:00 AM PST 14/APR/2016 5:00:00 AM PST
SYSDATE is in UTC and as of now is 13/APR/2016 8:15 AM
I tried this. But not sure abt the conversion using to_timestamp_tz
select JIRA_KEY,To_CHAR( SCH_END_TIME,'DD/MON/YY HH:MI:SS PM') as SCH_END_TIME
FROM HW_JIRA_STATUS WHERE
to_timestamp_tz(SYSDATE,'DD/MON/YY HH:MI:SS PM') between SCH_START_TIME and SCH_END_TIME
When you do
to_timestamp_tz(SYSDATE,'DD/MON/YY HH:MI:SS PM')
you're implicitly converting SYSDATE to a string using your NLS_DATE_FORMAT, and then converting that string to a timestamp with time zone - but you aren't specifying the time zone, so it will use the database time zone by default (which is what you want anyway).
Relying on NLS settings is dangerous, so you should at least use an expliclt format mask:
to_timestamp_tz(to_char(SYSDATE, 'DD/MON/YY HH:MI:SS PM'),'DD/MON/YY HH:MI:SS PM')
... but you can also cast between data types without converting to intermediate strings; e.g. to again use the DB server time zone:
cast(SYSDATE as timestamp with time zone)
You don't need to do any conversion yourself though; you can use SYSTIMESTAMP instead:
WHERE SYSTIMESTAMP between SCH_START_TIME and SCH_END_TIME;
That is already in the DB server's time zone.
Try this query
select JIRA_KEY,To_CHAR( SCH_END_TIME,'DD/MON/YY HH:MI:SS PM') as SCH_END_TIME
FROM HW_JIRA_STATUS
WHERE systimestamp AT TIME ZONE 'PST' between SCH_START_TIME and SCH_END_TIME
Related
I am using Oracle 19c.
I need to convert dates from GMT to EST and EDT.
I am using the following approach:
1. Get the destination time zone abbreviation for the p_date variable:
DEFINE p_date TO_DATE('03/11/2013 02:22:21', 'MM/DD/YYYY HH24:MI:SS');
SELECT TO_CHAR(FROM_TZ(CAST (&p_date AS TIMESTAMP), 'America/New_York'), 'TZD') INTO v_tzabbrev FROM DUAL;
Where:
p_date: is the date to be converted.
v_tzname: is the time zone name, such as America/New_York
v_tzabbrev: is the time zone abbreviation, such as 'EDT' or "EST" based on whether the date is during Daylight Saving Time or not
2. Convert the p_date using the time zone abbreviation obtained in #1
SELECT NEW_TIME(p_date, 'GMT', v_tzabbrev) INTO v_date FROM DUAL;
This seems to work. But, I believe the flaw is that it is using the GMT date to determine the destination time zone abbreviation, which is inaccurate.
For example, if p_date, in UTC, is '03/11/2013 02:22:21' and I need to convert it to 'America/New_York', Step #1 would return 'EDT', but this date in Eastern was actually "03/10/2013 21:22:21", which was before Daylight Saving started. So, it should actually be converted using "EST".
Daylight saving time in '2013 began at 2 a.m. on Sunday, March 10.
So, it seems that I need a way to take the GMT value and determine its new date in Eastern first, then apply additional logic based on whether that new date is EDT or EST.
Any assistance is appreciated.
You can define p_date directly as UTC time:
DEFINE p_date TO_TIMESTAMP_TZ('03/11/2013 02:22:21 UTC', 'MM/DD/YYYY HH24:MI:SS TZR');
SELECT TO_CHAR((&p_date AT TIME ZONE 'America/New_York'), 'TZD')
INTO v_tzabbrev
FROM DUAL;
Or in the statement:
DEFINE p_date TO_DATE('03/11/2013 02:22:21', 'MM/DD/YYYY HH24:MI:SS');
SELECT TO_CHAR((FROM_TZ(CAST(&p_date AS TIMESTAMP), 'UTC') AT TIME ZONE 'America/New_York'), 'TZD')
INTO v_tzabbrev
FROM DUAL;
Another possibility is to use SESSIONTIMEZONE implicitly, although I don't recommend this:
DEFINE p_date TO_DATE('03/11/2013 02:22:21', 'MM/DD/YYYY HH24:MI:SS');
ALTER SESSION SET TIME ZONE = 'UTC';
SELECT TO_CHAR((CAST(&p_date AS TIMESTAMP WITH TIME ZONE) AT TIME ZONE 'America/New_York'), 'TZD')
INTO v_tzabbrev
FROM DUAL;
"Daylight saving time in '2013 began at 2 a.m. on Sunday, March 10."
... which is correct, and you can see that happening with the UTC equivalent date/time as:
-- get New York DST start time as UTC
with cte (ts) as (
select timestamp '2013-03-10 01:59:59 America/New_York' from dual
union all
select timestamp '2013-03-10 03:00:00 America/New_York' from dual
)
select ts, to_char(ts, 'TZD') as tzd, ts at time zone 'UTC' as ts_utc
from cte
TS
TZD
TS_UTC
2013-03-10 01:59:59 AMERICA/NEW_YORK
EST
2013-03-10 06:59:59 UTC
2013-03-10 03:00:00 AMERICA/NEW_YORK
EDT
2013-03-10 07:00:00 UTC
but this date in Eastern was actually "03/10/2013 21:22:21", which was before Daylight Saving started.
No, it isn't, it's after DST started.
So, it should actually be converted using "EST".
No, it shouldn't. I'm afraid the premise of your question is wrong.
The conversion you are doing is getting the correct result:
-- get UTC timestamp as New York
with cte (ts) as (
select timestamp '2013-03-11 02:22:21 UTC' from dual
)
select ts as ts_utc, ts at time zone 'America/New_YORK' as ts, to_char(ts at time zone 'America/New_York', 'TZD') as tzd
from cte
TS_UTC
TS
TZD
2013-03-11 02:22:21 UTC
2013-03-10 22:22:21 AMERICA/NEW_YORK
EDT
fiddle
2013-03-11 02:22:21 UTC is after 2013-03-10 01:59:59 America/New_York, as it is the following day in UTC, and 19 hours after the New York DST switch occurred. In other words, 2013-03-11 02:22:21 UTC is 19 hours after 2012-03-10 07:00:00 UTC, which is the UTC equivalent of the EDT start-time from the first query above.
You seem to be confusing the date in your UTC value with the date that DST was applied in the USA that year.
Because the NEW_TIME() function is limited, I would prefer to use FROM_TZ and AT TIME ZONE, as Wernfried showed.
I have a csv file with data in timezones including CST and CDT.
For eg:
07-Mar-2017 11:00:00 PM CST
03-Oct-2017 11:00:00 PM CDT
The date field in the csv is being stored as a varchar2(30).
The target date field needs to be converted to the format shown below:
MM/DD/YYYY hh:mm
How can we go about doing this conversion in oracle considering we have two timezines in the source file?
Please help.
Thanks Much
Tina
Use TO_TIMESTAMP_TZ to read it as a TIMESTAMP WITH TIME ZONE data type. If you want to convert it to a common time zone then use AT TIME ZONE 'UTC' to convert it to the UTC time zone (as an example).
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE your_table ( value ) AS
SELECT '07-Mar-2017 11:00:00 PM CST' FROM DUAL UNION ALL
SELECT '03-Oct-2017 11:00:00 PM CDT' FROM DUAL UNION ALL
SELECT '03-Oct-2017 11:00:00 PM CST' FROM DUAL;
Query 1:
SELECT TO_CHAR(
TO_TIMESTAMP_TZ(
value,
'DD-MON-YYYY HH12:MI:SS AM TZD',
'NLS_DATE_LANGUAGE=American'
) AT TIME ZONE 'UTC',
'MM-DD-YYYY HH24:MI'
) AS utc_time
FROM your_table
Results:
| UTC_TIME |
|------------------|
| 03-07-2017 23:00 |
| 10-03-2017 23:00 |
| 10-03-2017 23:00 |
How to convert below string to Date in Oracle
Wed Jan 13 23:01:24 GMT 2016
Tried below and this get's date as
SELECT TO_CHAR(SYSDATE, 'DY MON DD HH24:MM:SS YYYY') FROM dual;
FRI AUG 26 14:08:04 2016
Eventually, Wanted something like this
SELECT TO_CHAR('Wed Jan 13 23:01:24 GMT 2016', 'DY MON DD HH24:MM:SS ??? YYYY') FROM dual;
If the time zone is always a recognised abbreviation you can do:
select to_timestamp_tz('Wed Jan 13 23:01:24 GMT 2016', 'Dy Mon DD HH24:MI:SS TZD YYYY')
from dual;
TO_TIMESTAMP_TZ('WEDJAN1323:01:24GMT2016','DYMONDDHH24:MI:SSTZDYYYY')
---------------------------------------------------------------------
2016-01-13 23:01:24 EUROPE/LONDON
You can't convert directly to a date because the time zone format elements aren't allowed in to_date(). If you had a fixed value - always GMT - you could ignore that by treating it as a literal, but you don't.
If you want it as a timestamp or a date, rather than a timestamp with time zone, you need to decide how to convert it. You can assume it's local time and essentially ignore the time zone by casting it, or you can adjust it to a specific time zone, e.g. UTC. There are various ways, here are a couple with a CTE to provide your sample and one in another zone (well, in summertime anyway so you get a different string):
with t (str) as (
select 'Wed Jan 13 23:01:24 GMT 2016' from dual
union all select 'Fri Aug 26 19:53:27 BST 2016' from dual
)
select to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY') as tstz,
cast(to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY') as timestamp) as ts,
cast(to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY') as date) as dt,
sys_extract_utc(to_timestamp_tz(str, 'Dy Mon DD HH24:MI:SS TZD YYYY')) as tsutc
from t;
TSTZ TS DT TSUTC
--------------------------------- ------------------- ------------------- -------------------
2016-01-13 23:01:24 EUROPE/LONDON 2016-01-13 23:01:24 2016-01-13 23:01:24 2016-01-13 23:01:24
2016-08-26 19:53:27 EUROPE/LONDON 2016-08-26 19:53:27 2016-08-26 19:53:27 2016-08-26 18:53:27
Exactly how you handle it depends on what you really need, of course.
Unfortunately that doesn't always work with abbreviations; Oracle doesn't necessarily recognise the values you see in Unix date command output, and the ones it does recognise aren't always available. Changing the session time zone can break it:
alter session set time_zone = 'America/Los_Angeles';
select to_timestamp_tz('Wed Jan 13 23:01:24 GMT 2016', 'Dy Mon DD HH24:MI:SS TZD YYYY')
from dual;
ORA-01857: not a valid time zone
You can change the session time zone to one that does recognise it (Europe/London) but that's a hack and won't work for all values anyway. It doesn't help that abbreviations can mean more than one thing.
If you have a list of known expected values and know what they really represent to you, you can swap the abbreviation for a region, but it doesn't really scale:
select to_timestamp_tz(
replace(replace('Wed Jan 13 23:01:24 GMT 2016', 'GMT', 'Europe/London'),
'BST', 'Europe/London'),
'Dy Mon DD HH24:MI:SS TZR YYYY') from dual;
Or with multiple output formats:
with t1 (str) as (
select 'Wed Jan 13 23:01:24 GMT 2016' from dual
union all select 'Fri Aug 26 19:53:27 BST 2016' from dual
),
t2 (adj_str) as (
select replace(replace(str, 'GMT', 'Europe/London'), 'BST', 'Europe/London')
from t1
)
select to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY') as tstz,
cast(to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY') as timestamp) as ts,
cast(to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY') as date) as dt,
sys_extract_utc(to_timestamp_tz(adj_str, 'Dy Mon DD HH24:MI:SS TZR YYYY')) as tsutc
from t2;
You'd need to have nested replace calls (or regexp_replace to reduce the repetition a little) for each abbreviation you expect; or could have a function that hides that mess away from your main query.
You need to use the TO_TIMESTAMP_TZ function.
The following example converts a character string to a value of TIMESTAMP WITH TIME ZONE:
SELECT TO_TIMESTAMP_TZ('1999-12-01 11:00:00 -8:00',
'YYYY-MM-DD HH:MI:SS TZH:TZM') FROM DUAL;
The -8:00 is the timezone.
https://docs.oracle.com/cd/B12037_01/server.101/b10759/functions179.htm#SQLRF06143
all dates which we store in oracle are in EDT(summer) and EST(winter). I need a way to convert that date to UTC/GMT.
The conversion should be based on the db date and not the servers local TZ.
In other words if the date in the resultset is between:
"11/02/2014 02:00:00" ---> "03/08/2015 01:59:59": TZ offset = "-0500"
"03/08/2015 02:00:00" ---> "11/01/2015 01:59:59": TZ offset = "-0400".
And same for previous years.
Is there a solution for that?
Assuming some_date_column is actually a date column then you can turn it into a timestamp with time zone using a cast (from date to timestamp) and the from_tz function with a region that has the EST/EDT change defined:
with t (some_date_column) as (
select to_date('11/02/2014 02:00:00', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('03/08/2014 01:59:59', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('03/08/2015 03:00:00', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('11/01/2015 00:59:59', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('11/01/2015 01:59:59', 'MM/DD/YYYY HH24:MI:SS') from dual
union all
select to_date('11/02/2015 02:00:00', 'MM/DD/YYYY HH24:MI:SS') from dual
)
select t.some_date_column,
cast(t.some_date_column as timestamp) as some_timestamp,
from_tz(cast(t.some_date_column as timestamp), 'America/New_York')
as some_timestamp_tz
from t;
SOME_DATE_COLUMN SOME_TIMESTAMP SOME_TIMESTAMP_TZ
------------------- ------------------- ---------------------------
11/02/2014 02:00:00 11/02/2014 02:00:00 11/02/2014 02:00:00 -05:00
03/08/2014 01:59:59 03/08/2014 01:59:59 03/08/2014 01:59:59 -05:00
03/08/2015 03:00:00 03/08/2015 03:00:00 03/08/2015 03:00:00 -04:00
11/01/2015 00:59:59 11/01/2015 00:59:59 11/01/2015 00:59:59 -04:00
11/01/2015 01:59:59 11/01/2015 01:59:59 11/01/2015 01:59:59 -05:00
11/02/2015 02:00:00 11/02/2015 02:00:00 11/02/2015 02:00:00 -05:00
This doesn't quite line up with the ranges in your question. There is no 02:00 when you move from EST to EDT, so I've used 03:00 in the demo CTE instead; and as the period between 01:00 and 02:00 is (sort of) repeated when you go the other way from EDT to EST the offset for a plain time in that hour is ambiguous, and Oracle is choosing to treat it as -05:00 rather than -04:00.
If you want the UTC equivalent of the EST/EDT time then you can then use at time zone, and optionally cast back to a date:
...
select t.some_date_column,
from_tz(cast(t.some_date_column as timestamp), 'America/New_York')
at time zone 'UTC' as utc_timestamp_tz,
cast(from_tz(cast(t.some_date_column as timestamp), 'America/New_York')
at time zone 'UTC' as date) as utc_date
from t;
SOME_DATE_COLUMN UTC_TIMESTAMP_TZ UTC_DATE
------------------- --------------------------- -------------------
11/02/2014 02:00:00 11/02/2014 07:00:00 +00:00 11/02/2014 07:00:00
03/08/2014 01:59:59 03/08/2014 06:59:59 +00:00 03/08/2014 06:59:59
03/08/2015 03:00:00 03/08/2015 07:00:00 +00:00 03/08/2015 07:00:00
11/01/2015 00:59:59 11/01/2015 04:59:59 +00:00 11/01/2015 04:59:59
11/01/2015 01:59:59 11/01/2015 06:59:59 +00:00 11/01/2015 06:59:59
11/02/2015 02:00:00 11/02/2015 07:00:00 +00:00 11/02/2015 07:00:00
If your original column is a timestamp (with no time zone information) rather than a date then you can skip the first cast from date to timestamp, but still use from_tz to specify it's original region.
Is it possible to display sysdate in the following format?
Wed Oct 16 15:04:44 MDT 2013
This comes out of unix date format.
echo `date`
EDIT: the latest version is missing timezone information. Also, I am not sure if this is the most elegant solution :
SELECT TO_CHAR (sysdate, 'DY') || ' ' || to_char(sysdate, 'MON DD') || ' ' || to_char(sysdate, 'HH24:MM:SS' ) || ' ' || to_char(sysdate, 'YYYY' )
FROM DUAL ;
sysdate returns value of date data type, which does not contain information about timezone. To be able to display abbreviated version of timezone region you need to operate on values of timestamp with time zone data types and use TZD format element in a date time format mask:
select to_char( cast(sysdate as timestamp with local time zone)
, 'Dy Mon dd hh24:mi:ss TZD yyyy') as res
from dual
Result:
RES
-------------------------------
Thu Oct 17 02:14:00 PDT 2013
Edit
Wed Oct 16:12:0 2013 is what i got
Try to explicitly specify exact time zone region for a session. Because there are might be several time zone regions associated with one offset and oracle wont be able to choose one and returns null. So before executing the query execute alter session set time_zone='<<specify_exact_time_zone_region>>'. For example:
SQL> alter session set time_zone='Canada/Mountain';
Session altered.
SQL> select to_char( cast(sysdate as timestamp with local time zone)
2 , 'Dy Mon dd hh24:mi:ss TZD yyyy') as res
3 from dual;
RES
-------------------------------
Thu Oct 17 02:51:14 MDT 2013