0

我编写了一个函数来将日期转换为 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 应用服务器进程调用函数时,为什么我无法获得本地时区缩写?

4

3 回答 3

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.
于 2012-02-09T21:38:33.357 回答
0

您是否比较了本地计算机和服务器上的 NLS_DATE_FORMAT?您可能会发现这方面的差异以及在传递日期时发生隐式转换的可能性可能是您的问题。

于 2012-02-09T22:26:03.503 回答
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通过使用提取,您将获得包含 DST 的当前缩写。

于 2012-02-10T16:04:40.607 回答