我编写了一个将日期转换为Unix时间戳的函数。无论当前的DST状态如何(例如EST或EDT),该函数都被写入工作。这是功能:
function unix_time_from_date(in_date in date) return number
as
ut number := 0;
tz varchar2(8) := '';
begin
-- Get the local timezone from the passed in date
-- Assuming the date supplied is for the local time zone
select
extract(
timezone_abbr from cast(in_date as timestamp with local time zone)
)
into tz
from dual;
-- Get the Unix timestamp
select
(new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (
86400)
into ut
from dual;
return ut;
end unix_time_from_date;
当我从JDeveloper这样的客户端执行它时,这个功能很有用。从我收集的内容来看,这是因为客户端正在向第一个查询提供时区信息。但是,如果我在从mod_plsql页面调用的过程中使用该函数,则会收到错误ORA-01857: not a valid time zone
。 new_time
函数抛出了此错误,因为tz
设置为'UNK'
。
所以,我实现了解决这个问题的方法:
function unix_time_from_date(in_date in date) return number
as
ut number := 0;
tz varchar2(8) := '';
begin
-- Get the local timezone from the passed in date
-- Assuming the date supplied is for the local time zone
select
extract(
timezone_abbr from cast(in_date as timestamp with local time zone)
)
into tz
from dual;
if tz = 'UNK' then
select
extract(
timezone_abbr from cast(sysdate as timestamp with local time zone)
)
into tz
from dual;
end if;
-- Get the Unix timestamp
select
(new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (
86400)
into ut
from dual;
return ut;
end unix_time_from_date;
除此之外,tz
设置为'UNK'
时仍然失败。有谁知道这里会发生什么?从Oracle Application Server进程调用函数时,为什么无法获取本地时区缩写?
答案 0 :(得分:0)
我想这不取决于您传递的日期参数。它可能取决于运行数据库服务器的操作系统设置。在JDeveloper中,它可能从您的计算机(OS)时区设置中获取。尝试在数据库服务器上执行ssh并在脚本中运行前两个查询(使用'DD-MON-YY'格式的实际日期进行第一次查询)。两者都应该返回'UNK'。 UNK(未知)可能是因为返回了多个时区。示例:在以下示例中,假设当前时区是CST(美国中部时间)。
SELECT NEW_TIME(SYSDATE, 'CST', 'GMT') FROM DUAL --returns the date in London.
SELECT TO_CHAR(NEW_TIME(SYSDATE, 'CST', 'GMT'),'HH24:MI') FROM DUAL --returns the time, based on the 24-hour clock, in London.
SELECT TO_CHAR(NEW_TIME(SYSDATE + (14 / 24), 'PST', 'PST'),'DD-MON-YY HH24:MI') FROM DUAL --returns the date and time in China.
SELECT TO_CHAR(NEW_TIME(SYSDATE + (diff / 24), ‘GMT’, ‘GMT’),’DD-MON-YY HH24:MI’) FROM DUAL; --returns the date and time of your office.
答案 1 :(得分:0)
您是否比较了本地计算机和服务器上的NLS_DATE_FORMAT?您可能会发现这里存在差异的组合,以及在传递日期时发生非法转换的可能性可能是您的问题。
答案 2 :(得分:0)
当调用它的会话没有设置时区信息时,写入的函数不起作用。因此,您需要明确指定源时区。以下函数解决了此问题(并更正了返回类型):
function unix_time_from_date
(
in_date in date,
in_src_tz in varchar2 default 'America/New_York'
)
return integer
as
ut integer := 0;
tz varchar2(8) := '';
tz_date timestamp with time zone;
tz_stmt varchar2(255);
begin
-- Get the local time zone abbreviation from the passed in date
tz_stmt := 'select systimestamp at time zone ''' || in_src_tz || ''' from dual';
execute immediate tz_stmt into tz_date;
select
extract(timezone_abbr from tz_date)
into tz
from dual;
-- Get the Unix timestamp
select
(new_time(in_date, tz, 'GMT') - to_date('01-JAN-1970', 'DD-MM-YYYY')) * (86400)
into ut
from dual;
return ut;
end unix_time_from_date;
请注意在函数中添加第二个参数。此参数in_src_tz
用于指示in_date
参数所在的时区。in_src_tz
的值应为tzname
列中v$timezone_names
列中列出的时区之一tzabbrev
表。
此外,由于时区有多个缩写,因此您无法简单地选择v$timezone_names
表中{{1}}列的值。通过使用提取,您将获得当前包含DST的缩写。