CST/CDT date to MM/DD/YYYY hh:mm in oracle - oracle

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 |

Related

Oracle convert from GMT to EST and EDT

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.

Converting a date in oracle

I need to convert one date in different formats:
Below is the example-
There is one field named as APRVL_DT and lets take 3 values of this column are
APRVL_DT
18-JUN-12 09.25.34.000000000 AM
02-JUL-12 09.46.42.000000000 AM
16-JAN-14 09.54.26.000000000 AM
not sure about the timezone.It may be UTC.
Now i want to convert this fields in the format where i'll get data according to daylight saving.So Output should be
New_APRVL_DT
18-JUN-12 01.25.34.000000000 PM
02-JUL-12 01.46.42.000000000 PM
16-JAN-14 02.54.26.000000000 PM
I written one code which is giving me data but not in daylightsaving format-
TO_CHAR(FROM_TZ (TO_TIMESTAMP (APRVL_DT , 'YYYY-MM-DD HH:MI:SS'), 'EST5EDT') AT TIME ZONE 'UTC', 'YYYY-MM-DD HH:MI:SS A.M.') As NEW_APRVL_DT
Please help me in this.
You seem to want to convert a string representing a plain timestamp that you know represents an EST/EDT time to UTC (though the description in the question and your conversion attempt contradict each other). You really should not be storing dates or timestamps as strings, but if that is what you are stuck with, you just need to convert to (and from) the right data type. So you can do:
select APRVL_DT,
TO_CHAR(
SYS_EXTRACT_UTC(
FROM_TZ(TO_TIMESTAMP(APRVL_DT, 'DD-MON-RR HH:MI:SS.FF AM'), 'America/New_York')
), 'DD-MON-RR HH:MI:SS.FF AM') AS NEW_APRVL_DT
from your_table
APRVL_DT NEW_APRVL_DT
------------------------------- -------------------------------
18-JUN-12 09.25.34.000000000 AM 18-JUN-12 01:25:34.000000000 PM
02-JUL-12 09.46.42.000000000 AM 02-JUL-12 01:46:42.000000000 PM
16-JAN-14 09.54.26.000000000 AM 16-JAN-14 02:54:26.000000000 PM
db<>fiddle
Although that is essentially what your attempt was already doing...
If your session date language doesn't, or might not, match the language used for the month abbreviations in your table then you can specify that in the query:
select APRVL_DT,
TO_CHAR(
SYS_EXTRACT_UTC(
FROM_TZ(TO_TIMESTAMP(APRVL_DT, 'DD-MON-RR HH:MI:SS.FF AM', 'NLS_DATE_LANGUAGE=ENGLISH'), 'America/New_York')
), 'DD-MON-RR HH:MI:SS.FF AM', 'NLS_DATE_LANGUAGE=ENGLISH') AS NEW_APRVL_DT
from your_table
db<>fiddle
There is one field named as APRVL_DT [...] not sure about the timezone. It may be UTC.
Now i want to convert this fields in the format where i'll get data according to daylight saving.
You have the time zones in the wrong order:
SELECT APRVL_DT,
FROM_TZ( APRVL_DT, 'UTC' ) AT TIME ZONE 'EST5EDT' As NEW_APRVL_DT
FROM table_name
Which, for the sample data:
CREATE TABLE table_name ( aprvl_dt TIMESTAMP );
INSERT INTO table_name ( aprvl_dt )
SELECT TIMESTAMP '2012-06-18 09:25:34.000000000' FROM DUAL UNION ALL
SELECT TIMESTAMP '2012-06-02 09:46:42.000000000' FROM DUAL UNION ALL
SELECT TIMESTAMP '2014-01-16 09:54:26.000000000' FROM DUAL;
Outputs:
APRVL_DT | NEW_APRVL_DT
:---------------------------- | :--------------------------------
2012-06-18 09:25:34.000000000 | 2012-06-18 05:25:34.000000000 EDT
2012-06-02 09:46:42.000000000 | 2012-06-02 05:46:42.000000000 EDT
2014-01-16 09:54:26.000000000 | 2014-01-16 04:54:26.000000000 EST
From this comment:
APRVL_DT has EST timezone.
SELECT APRVL_DT,
FROM_TZ( APRVL_DT, 'EST' ) AT TIME ZONE 'EST5EDT' As NEW_APRVL_DT
FROM table_name
Which outputs:
APRVL_DT | NEW_APRVL_DT
:---------------------------- | :--------------------------------
2012-06-18 09:25:34.000000000 | 2012-06-18 10:25:34.000000000 EDT
2012-06-02 09:46:42.000000000 | 2012-06-02 10:46:42.000000000 EDT
2014-01-16 09:54:26.000000000 | 2014-01-16 09:54:26.000000000 EST
db<>fiddle here

Daylight saving error

I would like to calculate time diff between to dates in a different time zone. I am converting this two times to Greenwich time. But when I am converting dates in Europe/Moscow timezone the offset is different although there is no daylight saving.
This is the case I checked:
SELECT TO_DATE('5/20/2018 10:05:00 PM','mm/dd/yyyy hh:mi:ss am'),
TO_DATE('5/20/2018 10:05:00 PM','mm/dd/yyyy hh:mi:ss am')
- extract(TIMEZONE_HOUR from from_tz (TO_TIMESTAMP('5/20/2018 10:05:00 PM','mm/dd/yyyy hh:mi:ss am') ,'GMT' ) at time zone 'Europe/Moscow')/24 deptime_GRINICH
from dual
UNION
SELECT TO_DATE('5/24/2018 11:35:00 PM','mm/dd/yyyy hh:mi:ss am'),
TO_DATE('5/24/2018 11:35:00 PM','mm/dd/yyyy hh:mi:ss am')
- extract(TIMEZONE_HOUR from from_tz (TO_TIMESTAMP('5/24/2018 11:35:00 PM','mm/dd/yyyy hh:mi:ss am') ,'GMT' ) at time zone 'Europe/Moscow')/24 deptime_GRINICH
from dual
And the results are:
Date date converting to Greenwich time zone
5/20/2018 10:05:00 PM 5/20/2018 6:05:00 PM --> hour difference 4 hours
5/24/2018 7:35:00 PM 5/24/2018 3:35:00 PM --> hour difference 4 hours
but 2018 Time Zones - Sochi is UTC + 3h
In October 2014 Russia changed their rule for Daylight-Saving. Your Timezone file at Oracle Database could be an old one which does not cover the recent changes. Verify version with
SELECT * FROM V$TIMEZONE_FILE;
and consider an upgrade, see Upgrading the Time Zone File and Timestamp with Time Zone Data
However, it seems to be a bug in Oracle. Have a look at my query which is a bit more clear than your example:
SELECT *
FROM NLS_SESSION_PARAMETERS
WHERE parameter LIKE 'NLS_TIMESTAMP_TZ_FORMAT';
PARAMETER VALUE
-------------------------- --------------------------------------
NLS_TIMESTAMP_TZ_FORMAT YYYY-MM-DD HH24:MI:SSfmXFF3 fmTZH:TZM
1 row selected.
SELECT
EXTRACT(TIMEZONE_HOUR FROM TIMESTAMP '2018-05-20 22:05:00 Europe/Moscow') AS TZ_HOUR,
TO_CHAR(TIMESTAMP '2018-05-20 22:05:00 Europe/Moscow', 'YYYY-MM-DD HH24:MI:SS TZH:TZM') AS ts2,
TIMESTAMP '2018-05-20 22:05:00 Europe/Moscow' AS ts3
FROM dual;
TZ_HOUR TS2 TS3
---------- ------------------------------ ----------------------------------
4 2018-05-20 22:05:00 +04:00 20.05.2018 22:05:00.000000000 +03:00
1 row selected.
That's really strange, because TZH:TZM, resp. EXTRACT(TIMEZONE_HOUR FROM ...) returns different value than default NLS_TIMESTAMP_TZ_FORMAT = ... TZH:TZM. For other time zones (e.g. Europe/Zurich) I get always 02:00 - as expected.
You may open a ticket at Oracle support.
I have two databases, an old and a new one. The old one does not reflect recent changes in Russian Daylight-Saving times, the newer one does. However, the error as above appears on both:
ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD HH24:MI:SS TZH:TZM';
SELECT filename, VERSION,
TO_CHAR(TIMESTAMP '2018-05-20 22:05:00 Europe/Moscow', 'TZH:TZM TZD') AS ts1,
TIMESTAMP '2018-05-20 22:05:00 Europe/Moscow' AS ts2,
TO_CHAR(TIMESTAMP '2018-01-20 22:05:00 Europe/Moscow', 'TZH:TZM TZD') AS ts3,
TIMESTAMP '2018-01-20 22:05:00 Europe/Moscow' AS ts4
FROM V$TIMEZONE_FILE;
Old (Daylight-Saving times still existing due to old timezlrg_14.dat file):
FILENAME VERSION TS1 TS2 TS3 TS4
---------------- -------- ----------- ------------------------------------ ----------- -------------------------------------
timezlrg_14.dat 14 +04:00 MSD 20.05.2018 22:05:00.000000000 +03:00 +03:00 MSK 20.01.2018 22:05:00.000000000 +03:00
New (no Daylight-Saving time changes):
FILENAME VERSION TS1 TS2 TS3 TS4
---------------- -------- ----------- ------------------------------------ ----------- -------------------------------------
timezlrg_18.dat 18 +04:00 MSK 20.05.2018 22:05:00.000000000 +03:00 +04:00 MSK 20.01.2018 22:05:00.000000000 +03:00

Oracle timezone convert UTC to PST

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

specifying a date/time format with timezone

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

Resources