我需要将 sysdate 和时间转换为特定的时区,如 EST。我不能假设我当前的时区。
如何在plsql中转换它?请帮我。
假设您有一个TIMESTAMP WITH TIME ZONE
(例如systimestamp
),您可以使用该AT TIME ZONE
语法。例如,我可以systimestamp
通过指定不同的时区名称来获取当前时区并将其转换为 UTC (GMT)、东部和太平洋时区。
SQL> ed
Wrote file afiedt.buf
1 select systimestamp at time zone 'UTC' current_time_in_utc,
2 systimestamp at time zone 'Us/Eastern' current_time_in_est,
3 systimestamp at time zone 'US/Pacific' current_time_in_pst
4* from dual
SQL> /
CURRENT_TIME_IN_UTC
---------------------------------------------------------------------------
CURRENT_TIME_IN_EST
---------------------------------------------------------------------------
CURRENT_TIME_IN_PST
---------------------------------------------------------------------------
26-APR-12 05.36.11.802000 PM UTC
26-APR-12 01.36.11.802000 PM US/EASTERN
26-APR-12 10.36.11.802000 AM US/PACIFIC
Oracle 已经有一个时区表:
SELECT tzname, tzabbrev from V$TIMEZONE_NAMES
SELECT TZ_OFFSET('US/Eastern') FROM DUAL;
获取 EPT 中的当前时间以用于 SQL 语句:
select to_timestamp(to_char(TRUNC(LOCALTIMESTAMP - 5/1440, 'MI'),'mm/dd/yyyy hh24:mi'),'mm/dd/yyyy hh24:mi') FROM DUAL;
Oracle 的 11g SQL 参考非常好,可在此处在线获取:http: //docs.oracle.com/cd/B28359_01/server.111/b28286/toc.htm
您可以快速查找以下功能,我相信您会发现这些功能会有所帮助:
tz_offset
更改会话集 TIME_ZONE = '+00:00'; -- 您现在将看到 UTC 时间而不是 EPT
不同时区的当前日期和时间
以当地通行时间返回当前日期和时间(sysdate)
Select sysdate from dual;
select LOCALTIMESTAMP FROM DUAL;
以 UTC 格式返回当前日期
select LOCALTIMESTAMP at time zone '+00:00' FROM DUAL
-- 尝试使用 localtimestamp、to_timestamp 和 to_timestamp_tz,而不是使用 sysdate 和 to_date。它们类似于 sysdate 和 to_date,但添加了时区功能。
select LOCALTIMESTAMP at time zone '+00:00' FROM DUAL; –- returns essentially the same as sysdate but in UTC
or
ALTER SESSION SET TIME_ZONE = 'UTC';
select LOCALTIMESTAMP FROM DUAL –- after setting session time_zone to ‘UTC’ this will now return a UTC timestamp
时区转换 以 UTC 格式获取当前时间以用于 SQL 语句。
-- Get current time in UTC format and subtract 5 minutes.
LOCALTIMESTAMP at time zone '+00:00' - 5/1440
-- Trunc the time to eliminate seconds
TRUNC(LOCALTIMESTAMP at time zone '+00:00' - 5/1440, 'MI')
-- Convert to characters then back to datetime.
to_timestamp(to_char(TRUNC(LOCALTIMESTAMP at time zone '+00:00' - 5/1440, 'MI'),'mm/dd/yyyy hh24:mi'),'mm/dd/yyyy hh24:mi')
-- Select from dual to show it works.
select to_timestamp(to_char(TRUNC(LOCALTIMESTAMP at time zone '+00:00' - 5/1440, 'MI'),'mm/dd/yyyy hh24:mi'),'mm/dd/yyyy hh24:mi') FROM DUAL;
Get the current time in EPT for use in a SQL statement.
-- Get current time in UTC format and subtract 5 minutes.
ALTER SESSION SET TIME_ZONE = 'US/Eastern'; -- set to EPT time
select LOCALTIMESTAMP from dual - 5/1440
-- Trunc the time to eliminate seconds
TRUNC(LOCALTIMESTAMP - 5/1440, 'MI')
-- Convert to characters then back to datetime.
to_timestamp(to_char(TRUNC(LOCALTIMESTAMP - 5/1440, 'MI'),'mm/dd/yyyy hh24:mi'),'mm/dd/yyyy hh24:mi')
-- Select from dual to show it works.
select to_timestamp(to_char(TRUNC(LOCALTIMESTAMP - 5/1440, 'MI'),'mm/dd/yyyy hh24:mi'),'mm/dd/yyyy hh24:mi') FROM DUAL;
返回 DB 和 Session 时区函数
ALTER SESSION SET TIME_ZONE = '+00:00'; -- you will now see times in UTC instead of EPT
ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY HH24:MI:SS';
ALTER SESSION SET TIME_ZONE = '+00:00'; -- you will now see times in UTC instead of EPT
ALTER SESSION SET TIME_ZONE = 'UTC'; -- set to UTC time same as command above
SELECT DBTIMEZONE , SESSIONTIMEZONE, CURRENT_TIMESTAMP, LOCALTIMESTAMP, systimestamp, sysdate FROM DUAL; -- see the results
ALTER SESSION SET TIME_ZONE = 'US/Eastern'; -- set to EPT time
SELECT DBTIMEZONE , SESSIONTIMEZONE, CURRENT_TIMESTAMP, LOCALTIMESTAMP, systimestamp, sysdate FROM DUAL; -- see the results
SELECT TO_TIMESTAMP_TZ('05/16/2014 11:26:48 -04:00',
'MM/DD/YYYY HH:MI:SS TZH:TZM') FROM DUAL;
SELECT tzname, tzabbrev from V$TIMEZONE_NAMES where tzabbrev = 'EPT';
SELECT TZ_OFFSET('US/Eastern') FROM DUAL;
-- The following example casts a null column in a UNION operation as TIMESTAMP WITH LOCAL TIME ZONE using the sample tables oe.order_items and oe.orders:
SELECT order_id, line_item_id,
CAST(NULL AS TIMESTAMP WITH LOCAL TIME ZONE) order_date
FROM order_items
UNION
SELECT order_id, to_number(null), order_date
FROM orders;
日期时间和时区 (TO_TIMESTAMP_TZ)
TO_TIMESTAMP_TZ converts char of CHAR, VARCHAR2, NCHAR, or NVARCHAR2 datatype to a value of TIMESTAMP WITH TIME ZONEdatatype.
示例:以下示例将字符串转换为 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;
TO_TIMESTAMP_TZ('1999-12-0111:00:00-08:00','YYYY-MM-DDHH:MI:SSTZH:TZM')
以下示例使用示例表 oe.order_items 和 oe.orders 将 UNION 操作中的空列转换为 TIMESTAMP WITH LOCAL TIME ZONE:
SELECT order_id, line_item_id,
CAST(NULL AS TIMESTAMP WITH LOCAL TIME ZONE) order_date
FROM order_items
UNION
SELECT order_id, to_number(null), order_date
FROM orders;
设置日期和时间格式
ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY HH24:MI:SS';
SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP FROM DUAL;
设置当前/本地时区
ALTER SESSION SET TIME_ZONE = '-5:00';
ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY HH24:MI:SS';
SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP FROM DUAL;
当地时间 (LOCALTIMESTAMP)
LOCALTIMESTAMP 以数据类型 TIMESTAMP 的值返回会话时区中的当前日期和时间。此函数与 CURRENT_TIMESTAMP 的区别在于 LOCALTIMESTAMP 返回一个 TIMESTAMP 值,而 CURRENT_TIMESTAMP 返回一个 TIMESTAMP WITH TIME ZONE 值。
ALTER SESSION SET TIME_ZONE = '-5:00';
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
SELECT CURRENT_TIMESTAMP, LOCALTIMESTAMP FROM DUAL;
以下语句使用正确的格式掩码来匹配 LOCALTIMESTAMP 的返回类型:
INSERT INTO local_test VALUES
(TO_TIMESTAMP(LOCALTIMESTAMP, 'DD-MON-RR HH.MI.SSXFF PM'));
The code above is required to include the TIME ZONE portion of the return type of the function
当前时间戳 (CURRENT_TIMESTAMP)
CURRENT_TIMESTAMP 以数据类型 TIMESTAMP WITH TIMEZONE 的值返回会话时区中的当前日期和时间。时区偏移量反映了 SQL 会话的当前本地时间
ALTER SESSION SET TIME_ZONE = '-5:0';
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
SELECT SESSIONTIMEZONE, CURRENT_TIMESTAMP FROM DUAL;
这个怎么样?
select to_timestamp_tz(to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') || ' ' || 'FROM_TIME_ZONE', 'YYYY-MM-DD HH24:MI:SS TZR') at time zone 'TO_TIME_ZONE'
from dual;
尝试这个:
CREATE TABLE TIMEZONES (ZONE CHAR(1) PRIMARY KEY,
NAMES VARCHAR2(25) NOT NULL,
OFFSET_HOURS NUMBER NOT NULL);
按如下方式填充它:
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('Z', 'GMT', 0);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('N', '-1', -1);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('O', '-2', -2);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('P', '-3', -3);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('Q', '-4 EDT', -4);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('R', 'EST CDT', -5);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('S', 'CST MDT', -6);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('T', 'MST PDT', -7);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('U', 'PST', -8);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('V', '-9', -9);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('W', '-10', -10);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('X', '-11', -11);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('Y', '-12', -12);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('A', '1', -1);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('B', '2', -2);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('C', '3', -3);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('D', '4', -4);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('E', '5', -5);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('F', '6', -6);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('G', '7', -7);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('H', '8', -8);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('I', '9', -9);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('K', '10', -10);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('L', '11', -11);
INSERT INTO TIMEZONES (ZONE, NAMES, OFFSET_HOURS) VALUES ('M', '12', -12);
鉴于上述情况,您可以这样做
SELECT SYS_EXTRACT_UTC(SYSTIMESTAMP) + (tz.OFFSET_HOURS / 24)
FROM TIMEZONES tz
WHERE tz.NAMES LIKE '%EDT%';
或者
WHERE tz.ZONE = 'Q'
获取-4时区的当地时间。
分享和享受。
到目前为止,所有方法在使用当前时间戳时都可以很好地工作。然而,我注意到甲骨文tz_offset
会给你主要的时间偏移量。例如,七月,
SELECT TZ_OFFSET('US/Eastern') FROM DUAL;
结果为“-04:00”。1 月,相同的语句导致“-05:00”。因此,如果要转换存储在数据库中的日期(而不是当前系统或会话时间),则必须进行一些开发。
你可能会注意到
SELECT TZ_OFFSET('EST') FROM DUAL;
总是返回“-05:00”。不幸的是,对其他美国标准时间(中部、山区和太平洋)的快速测试显示了不同的结果。运行以下命令自己查看。在 DST 生效时,我在 6 月 16 日运行了以下命令。
SELECT TZ_OFFSET('US/Eastern'), TZ_OFFSET('EST'), TZ_OFFSET('EST5EDT') FROM DUAL;
SELECT TZ_OFFSET('US/Central'), TZ_OFFSET('CST'), TZ_OFFSET('CST6CDT') FROM DUAL;
SELECT TZ_OFFSET('US/Mountain'), TZ_OFFSET('MST'), TZ_OFFSET('MST7MDT') FROM DUAL;
SELECT TZ_OFFSET('US/Pacific'), TZ_OFFSET('PST'), TZ_OFFSET('PST8PDT') FROM DUAL;
-04:00 -05:00 -04:00
-05:00 -05:00 -05:00
-06:00 -07:00 -06:00
-07:00 -07:00 -07:00
结果有些令人沮丧。从快速采样来看,几乎所有 tz_offset 查询似乎都以当前流行时间响应。这在您处理当前时间的转换时很有用,但在处理从数据库中提取的时间时会变得平淡无奇。
现在,我可以编写代码来确定我是处于标准时间还是现行时间。但是,我看不到在tz_offset
标准时间或日光时间持续拉动 a 的方法,只是普遍存在。
这使得开发人员需要像上面 Bob Jarvis 所做的那样创建自己的表来解决问题,就像我在下面的代码中所做的那样。
ALTER SESSION SET NLS_DATE_FORMAT = 'MM/DD/YYYY HH24:MI:SS';
Declare
-- ******** User declarations begin here ******** --
-- ******** User declarations end here ******** --
/******************* All Declarations of Variables and Functions below this point support Time Zone Conversion (Convert_TZ function) *******************/
-- TimeZone Conversion Procedure
-- User Input (Parameters)
input_date date := TO_TIMESTAMP_TZ('7/1/2009 18:00','mm/dd/yyyy hh24:mi'); -- Try: LocalTimestamp; or TO_TIMESTAMP('2/1/2009 13:00','mm/dd/yyyy hh24:mi')
--input_date date := LocalTimestamp;
input_TZ varchar(3) := 'GMT'; -- Exmaples: EST, EDT or EPT for Eastern Standard, Daylight or Prevailing, respectively.
output_TZ varchar(3) := 'EPT'; --
-- Variables
type date_array is table of date;
return_date date := localtimestamp;
temp_date date := to_date('10/27/1974 02:00','mm/dd/yyyy hh24:mi');
type str_array is table of varchar2(10);
dow_list str_array;
Function dst_start_stop (input_date DATE)
RETURN date_array
AS
year_part number(4);
start_week number(1) := 0; -- week of month: -1=last, 1=1st, 2=nd, 0=fixed date (like 1974 and 1975)
stop_week number(1) := 0; -- week of month: -1=last, 1=1st, 2=nd, 0=fixed date (like 1974 and 1975)
dst_start date := to_date('01/06/1974 23:59','mm/dd/yyyy hh24:mi');
dst_stop date := to_date('10/27/1974 23:59','mm/dd/yyyy hh24:mi');
dst_date date := dst_start;
dst_msg varchar2(500) := ' ';
inc_dec number := 0;
Cnt number(1) := 0;
dst_dow number(1) := 1; -- 1=Sunday, 2=Monday, etc.
i number;
dst_range date_array;
BEGIN
dst_range := date_array();
dst_range.extend(2);
dst_range(1) := temp_date;
dst_range(2) := temp_date;
DBMS_OUTPUT.PUT_LINE(' ** Start: dst_start_stop Func **');
--insert into dst_range values(dst_start,dst_stop);
--dst_range(1) := dst_start;
--dst_range(2) := dst_stop;
year_part := to_number(to_char(input_date,'YYYY'));
DBMS_OUTPUT.PUT_LINE(' Year: '||year_part);
-- Determine DST formula based on year of input_date
If year_part > 9999 Then -- Invalid TempYear > 9999
dst_msg := 'N/A. I can''t guess if DST will be applied after 9999. Standard Time returned. ';
Goto found_start_stop;
ElsIf year_part >= 2007 Then -- 2007 forward. Latest DST Rules used after 2007.
dst_msg := '2007 forward: Third National DST Standard. ';
--dst_msg := dst_msg || 'Spring Forward 2:00 AM second Sunday in March (skip 02:00:00 through 02:59:59, I.E. skip from 01:59:59 to 03:00:00). '
--dst_msg := dst_msg || 'Fall Back 2:00 AM first Sunday in November (repeat 02:00:00 to 02:59:59, I.E. jump back from 02:59:59 to 02:00:00 once). '
DBMS_OUTPUT.PUT_LINE(' '||dst_msg);
dst_start := to_date('03/01/'||year_part||' 02:00','mm/dd/yyyy hh24:mi');
start_week := 2; -- 2nd Sunday in March
dst_stop := to_date('11/01/'||year_part||' 02:00','mm/dd/yyyy hh24:mi');
stop_week := 1; -- 1st Sunday in November
ElsIf year_part >= 1987 Then -- 1987 thru 2006.
dst_msg := '1987 thru 2006: Second National DST Standard. ';
--dst_msg := dst_msg || 'Spring Forward 2:00 AM first Sunday in April (skip 02:00:00 through 02:59:59, I.E. skip from 01:59:59 to 03:00:00). ';
--dst_msg := dst_msg || 'Fall Back 2:00 AM last Sunday in October (repeat 02:00:00 to 02:59:59, I.E. jump back from 02:59:59 to 02:00:00 once). ';
DBMS_OUTPUT.PUT_LINE(' '||dst_msg);
start_week := 1;
dst_start := to_date('04/01/'||year_part||' 02:00','mm/dd/yyyy hh24:mi');
stop_week := -1;
dst_stop := to_date('10/31/'||year_part||' 02:00','mm/dd/yyyy hh24:mi');
ElsIf year_part >= 1976 Then -- 1976 thru 1986 OLD DST Rules used 1961 thru 1973.
dst_msg := '1976 thru 1986: First National DST Standard (resumed after 1974-1975 extended DST trials). ';
--dst_msg := dst_msg || 'Spring Forward 2:00 AM last Sunday in April (skip 02:00:00 through 02:59:59, I.E. skip from 01:59:59 to 03:00:00). ';
--dst_msg := dst_msg || 'Fall Back 2:00 AM last Sunday in October (repeat 02:00:00 to 02:59:59, I.E. jump back from 02:59:59 to 02:00:00 once). ';
DBMS_OUTPUT.PUT_LINE(' '||dst_msg);
start_week := -1;
dst_start := to_date('04/30/'||year_part||' 02:00','mm/dd/yyyy hh24:mi');
stop_week := -1;
dst_stop := to_date('10/31/'||year_part||' 02:00','mm/dd/yyyy hh24:mi');
ElsIf year_part = 1975 Then -- 1975 Trial.
dst_msg := '1975 Trial of Extended DST. ';
--dst_msg := dst_msg || 'Spring Forward 2:00 AM Feb 23 (skip 02:00:00 through 02:59:59, I.E. skip from 01:59:59 to 03:00:00). ';
--dst_msg := dst_msg || 'Fall Back 2:00 AM Oct 26, the last Sun in Oct (repeat 02:00:00 to 02:59:59, I.E. jump back from 02:59:59 to 02:00:00 once). ';
DBMS_OUTPUT.PUT_LINE(' '||dst_msg);
dst_start := to_date('02/23/1975 02:00','mm/dd/yyyy hh24:mi');
dst_stop := to_date('10/26/1974 02:00','mm/dd/yyyy hh24:mi');
Goto found_start_stop;
ElsIf year_part = 1974 Then -- 1974 Trial.
dst_msg := '1974 Trial of Extended DST. ';
--dst_msg := dst_msg || 'Spring Forward 2:00 AM Jan 6 (skip 02:00:00 through 02:59:59, I.E. skip from 01:59:59 to 03:00:00)). ';
--dst_msg := dst_msg || 'Fall Back 2:00 AM Oct 27 (repeat 02:00:00 to 02:59:59, I.E. jump back from 02:59:59 to 02:00:00 once). ';
DBMS_OUTPUT.PUT_LINE(' '||dst_msg);
dst_start := to_date('01/06/1974 02:00','mm/dd/yyyy hh24:mi');
dst_stop := to_date('10/27/1974 02:00','mm/dd/yyyy hh24:mi');
Goto found_start_stop;
ElsIf year_part >= 1961 Then -- 1961 thru 1973 First National DST Standard.
dst_msg := '1961 thru 1973: First National DST Standard. ';
--dst_msg := dst_msg || 'Spring Forward 2:00 AM last Sunday in April (skip 02:00:00 through 02:59:59, I.E. skip from 01:59:59 to 03:00:00). ';
--dst_msg := dst_msg || 'Fall Back 2:00 AM last Sunday in October (repeat 02:00:00 to 02:59:59, I.E. jump back from 02:59:59 to 02:00:00 once). ';
start_week := -1;
dst_start := to_date('04/30/'||input_date||' 02:00','mm/dd/yyyy hh24:mi');
stop_week := -1;
dst_stop := to_date('10/31/'||year_part||' 02:00','mm/dd/yyyy hh24:mi');
ElsIf year_part >=1900 Then -- DST was applied inconsistently or not at all
dst_msg := 'N/A. Before 1961, DST was applied inconsistently across states or not at all. Standard Time returned. ';
Goto found_start_stop;
ElsIf year_part < 1900 Then -- Invalid year_part
dst_msg := 'N/A. DST never active before 1900';
Goto found_start_stop;
Else -- Invalid year_part
dst_msg := 'N/A. Error. Invalid datetime value.';
Goto found_start_stop;
End If;
DBMS_OUTPUT.PUT_LINE(' The code specified the following DST rules for the input date ('||input_date||'). '||dst_msg);
if start_week > 0 then
DBMS_OUTPUT.PUT_LINE(' Start on '||dow_list(dst_dow)||' #'||start_week||' of '||trunc(dst_start,'W')||'. ');
else
DBMS_OUTPUT.PUT_LINE(' Starts '||start_week||' from the last '||dow_list(dst_dow)||' of '||trunc(dst_start,'W')||'. ');
end if;
if stop_week > 0 then
DBMS_OUTPUT.PUT_LINE(' End on '||dow_list(dst_dow)||' #'||stop_week||' of '||trunc(dst_stop,'W')||'. ');
else
DBMS_OUTPUT.PUT_LINE(' Ends '||stop_week||' from the last '||dow_list(dst_dow)||' of '||trunc(dst_stop,'W')||'. ');
end if;
DBMS_OUTPUT.PUT_LINE(' ');
/* Apply formula determined above to find dst start and stop times for the year of the input_date.
This section is skipped if start/stop already determined or indeterminant.
*/
-- DstStartDay
inc_dec := start_week/abs(start_week); -- results in +1 or -1
Cnt := 0; i:=0;
while (Cnt < abs(start_week) and i<20) loop
i:=i+1;
if (to_char(dst_start,'D') = dst_dow) then
Cnt := Cnt + 1;
--DBMS_OUTPUT.PUT_LINE(' Found '||dow_list(dst_dow))||' '||Cnt||': '||dst_start)
end if;
if (Cnt < abs(start_week)) then
dst_start := dst_start + inc_dec;
end if;
end loop;
case inc_dec
when 1 then
DBMS_OUTPUT.PUT_LINE(' Spring forward on '||dow_list(dst_dow)||' #'||Cnt||' of the month: '||dst_start);
else
DBMS_OUTPUT.PUT_LINE(' Spring forward on the last'||dow_list(dst_dow)||'of the month: '||dst_start);
end case;
-- DstStopDay
inc_dec := stop_week/abs(stop_week); -- results in +1 or -1
Cnt := 0; i :=0;
while (Cnt < abs(stop_week) and i <20) loop -- to_char(dst_stop,'D') > 1 loop
i:=i+1;
if (to_char(dst_stop,'D') = dst_dow) then
dst_stop := dst_stop + inc_dec;
Cnt := Cnt + 1;
end if;
if (Cnt < abs(stop_week)) then
dst_stop := dst_stop + inc_dec;
end if;
end loop;
case inc_dec
when 1 then
DBMS_OUTPUT.PUT_LINE(' Fall back on '||dow_list(dst_dow)||' #'||Cnt||' of the month: '||dst_stop);
else
DBMS_OUTPUT.PUT_LINE(' Fall back on the last'||dow_list(dst_dow)||'of the month: '||dst_stop);
end case;
<<found_start_stop>>
dst_range(1) := dst_start;
DBMS_OUTPUT.PUT_LINE(' dst_range(1): '||to_char(dst_range(1),'mm/dd/yyyy hh24:mi')||' = '||dst_start);
dst_range(2) := dst_stop;
DBMS_OUTPUT.PUT_LINE(' dst_range(2): '||to_char(dst_range(2),'mm/dd/yyyy hh24:mi')||' = '||dst_stop);
DBMS_OUTPUT.PUT_LINE(' ** Finish: dst_start_stop Func **');
Return dst_range;
END dst_start_stop;
Function is_dst_now
Return boolean
AS
--type date_array is table of date;
dst_range date_array;
curr_time date := LocalTimestamp;
Begin
dst_range := date_array();
dst_range.extend(2);
dst_range := dst_start_stop(curr_time);
If (dst_range(1) <= curr_time and curr_time < dst_range(2)) then
DBMS_OUTPUT.PUT_LINE('DST is active.');
Return True;
Else
DBMS_OUTPUT.PUT_LINE('DST is NOT active.');
Return False;
End If;
End;
FUNCTION dst_offset (prevailing_date DATE, dst_start DATE, dst_stop DATE)
RETURN number
AS
offset_days number :=0;
BEGIN
DBMS_OUTPUT.PUT_LINE(' Starting dst_offset sub-function:');
DBMS_OUTPUT.PUT_LINE(' where (input date, DST start, DST stop) = '||to_char(prevailing_date,'mm/dd/yyyy hh24:mi')
||', '||to_char(dst_start,'mm/dd/yyyy hh24:mi')||', '||to_char(dst_stop,'mm/dd/yyyy hh24:mi'));
If (dst_start <= prevailing_date and prevailing_date < dst_stop) then
offset_days :=1/24;
DBMS_OUTPUT.PUT_LINE(' input date is between dst start and stop');
Else
offset_days :=0;
DBMS_OUTPUT.PUT_LINE(' input date is not between dst start and stop');
End If;
DBMS_OUTPUT.PUT_LINE(' Result: DST Offset days = '||offset_days);
DBMS_OUTPUT.PUT_LINE(' hours = '||(offset_days*24));
Return offset_days;
END dst_offset;
-- Begin --move this down under the function -- ******************
FUNCTION Convert_TZ (input_date DATE, input_tz varchar2, output_tz varchar2)
RETURN date
AS
-- Variables
input_sz varchar(3) := substr(input_TZ,1,1)||'S'||substr(input_TZ,3,1);
input_sz varchar(3) := substr(output_TZ,1,1)||'S'||substr(output_TZ,3,1);
temp_str varchar2(1000);
dst_range date_array;
input_dst_offset number := 0;
input_tz_offset number := 0;
input_date_st date; --standard time
gmt_date date;
output_dst_offset number := 0;
output_tz_offset number := 0;
output_date date;
output_date_pt date; -- prevailing time
tz_offset_str varchar2(30);
--orig_nls_date_format varchar2(30) := NLS_DATE_FORMAT;
--TempYear number(4,0) := to_char(TempDate,'YYYY'); -- or := trunc(PrevailingTime, YYYY);
BEGIN
DBMS_OUTPUT.PUT_LINE('Starting Pl/sql procedure. ');
DBMS_OUTPUT.PUT_LINE('Input Date: '||to_char(input_date,'mm/dd/yyyy hh24:mi')||' '||input_tz||'. ');
-- Find DST start/stop dates
dst_range := date_array();
dst_range.extend(2);
dst_range := dst_start_stop(input_date);
DBMS_OUTPUT.PUT_LINE('DST date range determined. ');
DBMS_OUTPUT.PUT_LINE(' dst_range(1): '||to_char(dst_range(1),'mm/dd/yyyy hh24:mi')||' = '||dst_range(1));
DBMS_OUTPUT.PUT_LINE(' dst_range(2): '||to_char(dst_range(2),'mm/dd/yyyy hh24:mi')||' = '||dst_range(2));
-- Convert Input Date from input time zone to GMT
If upper(input_TZ) in ('GMT','UCT') then
-- If input TZ is GMT, we can skip this conversion!
DBMS_OUTPUT.PUT_LINE(' Input Time is ('||to_char(input_date,'mm/dd/yyyy hh24:mi')||' '
||input_tz||' GMT). No conversion required. ');
input_tz_offset := 0;
input_dst_offset := 0;
gmt_date := input_date;
Else
-- Convert from local prevailing to local standard time
-- Get input_dst_offset
Case upper(substr(input_TZ,2,1))
When 'S' then
-- already in standard time, not conversion needed.
input_dst_offset := 0; -- duplicative
DBMS_OUTPUT.PUT_LINE('Standard time ('||input_tz||') entered; no dst offset.' );
--input_tz_offset := input_tz_offset;
Else
-- run dst_offset function to convert from prevailing or daylight time to standard time.
input_dst_offset := dst_offset(input_date, dst_range(1), dst_range(2));
input_date_st := input_date - input_dst_offset;
DBMS_OUTPUT.PUT_LINE('Daylight Saving Time Effective ('||to_char(input_date,'mm/dd/yyyy hh24:mi')||' '
||input_tz||'); 1 hour offset; input DST offset = '||input_dst_offset);
DBMS_OUTPUT.PUT_LINE(' where (input_date, dst_start, dst_stop) = '
||to_char(input_date,'mm/dd/yyyy hh24:mi')
||' '||input_tz||', '||dst_range(1)||', '||dst_range(2)||', ');
DBMS_OUTPUT.PUT_LINE(' which adjusts '||to_char(input_date,'mm/dd/yyyy hh24:mi')||' '||input_tz
||' daylight to '||input_date_st||' standard time. ');
End Case;
-- Convert from local standard time to GMT
SELECT TZ_OFFSET((SELECT max(tzname) FROM V$TIMEZONE_NAMES where tzabbrev = input_TZ))
INTO tz_offset_str
FROM DUAL;
input_tz_offset := ( substr(tz_offset_str,1,3)/24 + substr(tz_offset_str,5,2)/1440 );
If is_dst_now then
input_tz_offset := input_tz_offset - 1/24;
End if;
DBMS_OUTPUT.PUT_LINE(' input_tz_offset (fractional days): '||input_tz_offset||'. ');
DBMS_OUTPUT.PUT_LINE(' input_tz_offset (hours): '||input_tz_offset*24||'. ');
gmt_date := input_date_st - input_tz_offset;
End If;
-- Convert input date from GMT to requested output time zone
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('Starting output_date analysis. ');
If upper(output_TZ) in ('GMT','UCT') then
-- If desired output TZ is GMT, we can skip this conversion!
output_tz_offset := 0;
output_dst_offset := 0;
output_date := gmt_date;
DBMS_OUTPUT.PUT_LINE(' Requested output format is GMT: ('||to_char(output_date,'mm/dd/yyyy hh24:mi')||' '||output_tz||'). No conversion required. ');
Else
-- Get output_dst_offset
Case upper(substr(output_TZ,2,1))
When 'S' then
output_dst_offset := 0; -- duplicative
DBMS_OUTPUT.PUT_LINE('Standard time ('||output_TZ||') entered; no dst offset.' );
Else
output_dst_offset := dst_offset(gmt_date + output_tz_offset, dst_range(1), dst_range(2));
End Case;
-- Convert from GMT to local standard time
SELECT TZ_OFFSET((SELECT max(tzname) FROM V$TIMEZONE_NAMES where tzabbrev = output_TZ)) INTO tz_offset_str FROM DUAL;
output_tz_offset := ( substr(tz_offset_str,1,3)/24 + substr(tz_offset_str,5,2)/1440 );
DBMS_OUTPUT.PUT_LINE(' output_tz_offset (fractional days): '||output_tz_offset||'. ');
DBMS_OUTPUT.PUT_LINE(' output_tz_offset (hours): '||output_tz_offset*24||'. ');
If is_dst_now then
output_tz_offset := output_tz_offset - 1/24;
DBMS_OUTPUT.PUT_LINE(' tz_offset correction... ');
DBMS_OUTPUT.PUT_LINE(' output_tz_offset (fractional days): '||output_tz_offset||'. ');
DBMS_OUTPUT.PUT_LINE(' output_tz_offset (hours): '||output_tz_offset*24||'. ');
End if;
output_date := gmt_date + output_tz_offset + output_dst_offset;
DBMS_OUTPUT.PUT_LINE(' gmt_date: '||gmt_date);
DBMS_OUTPUT.PUT_LINE(' output_tz_offset: '||output_tz_offset);
DBMS_OUTPUT.PUT_LINE(' output_dst_offset: '||output_dst_offset);
DBMS_OUTPUT.PUT_LINE('Daylight Saving Time ('||output_TZ||') offset = '||output_dst_offset);
DBMS_OUTPUT.PUT_LINE(' where (output_date, dst_start, DST_stop) = '||output_date||', '||dst_range(1)||', '||dst_range(2));
DBMS_OUTPUT.PUT_LINE(' which adjusts '||output_date||' standard to '||output_date_pt||' daylight time. ');
End If;
DBMS_OUTPUT.PUT_LINE('Output Date = '||to_char(output_date,'mm/dd/yyyy hh24:mi')||' '||output_tz||'. ');
Goto AllDone;
<<FoundError>>
<<AllDone>>
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('*** Results ***');
DBMS_OUTPUT.PUT_LINE(' ');
if input_dst_offset <> 0 then
temp_str := 'daylight saving';
else
temp_str := 'standard';
end if;
DBMS_OUTPUT.PUT_LINE(' Input Date: '||to_char(input_date,'mm/dd/yyyy hh24:mi')||' '||input_tz||', which falls in '||temp_str||' time. ');
DBMS_OUTPUT.PUT_LINE(' GMT Date: '||to_char(gmt_date,'mm/dd/yyyy hh24:mi')||' UTC/GMT. ');
DBMS_OUTPUT.PUT_LINE(' Output Date: '||to_char(output_date,'mm/dd/yyyy hh24:mi')||' UTC/GMT. ');
if output_dst_offset <> 0 then
temp_str := 'daylight saving';
else
temp_str := 'standard';
end if;
DBMS_OUTPUT.PUT_LINE(' All Done. Return Value: '||to_char(output_date,'mm/dd/yyyy hh24:mi')||' '||output_tz||'. ');
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('*** End of Results ***');
DBMS_OUTPUT.PUT_LINE(' ');
DBMS_OUTPUT.PUT_LINE('LocalTimestamp EPT: '||LocalTimestamp);
DBMS_OUTPUT.PUT_LINE('LocalTimestamp GMT:'||LOCALTIMESTAMP at time zone '+00:00');
Return output_date;
END;
/*********************** End of Declarations of Variables and Functions for Time Zone Conversion (Convert_TZ function) *********************/
Begin
/*********************** Start of Procedural Code for Time Zone Conversion (Convert_TZ function) *********************/
/* DOW list is required for Time Zone Conversion (Convert_TZ function) and should not be deleted. */
dow_list := str_array();
dow_list.extend(7);
dow_list(1) := 'Sun';
dow_list(2) := 'Mon';
dow_list(3) := 'Tue';
dow_list(4) := 'Wed';
dow_list(5) := 'Thu';
dow_list(6) := 'Fri';
dow_list(7) := 'Sat';
/* Next 2 lines are example of use of Time Zone Conversion (Convert_TZ function). */
return_date := Convert_TZ (input_date, input_tz, output_tz);
DBMS_OUTPUT.PUT_LINE('ta-dah! '||return_date);
/*********************** End of Procedural Code for Time Zone Conversion (Convert_TZ function) *********************/
-- ******** User coded begins here ******** --
End;
RTRIM( TO_CHAR( systimestamp at time zone 'GMT', 'DD-MON-YYYY HH24:MI:SS TZR' ))
RTRIM( TO_CHAR( systimestamp at time zone 'EST', 'DD-MON-YYYY HH24:MI:SS TZR' ))
RTRIM( TO_CHAR( systimestamp at time zone 'PST', 'DD-MON-YYYY HH24:MI:SS TZR' ))
output:
05-NOV-2014 17:20:10 GMT
05-NOV-2014 12:20:10 EST
05-NOV-2014 09:20:10 PST
substr('05-NOV-2014 09:20:10 PST', -3, 3) will return 'PST'
RTRIM (EXTRACT (HOUR from systimestamp ))
output: 17 (notice the 17 is in GMT time)