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 Application Server プロセスから呼び出されたときに、ローカル タイム ゾーンの省略形を取得できないのはなぜですか?

4

3 に答える 3

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;

関数に2番目のパラメーターが追加されていることに注意してください。このパラメーターはin_src_tz、パラメーターがどのタイムゾーンにあるかを示すために使用されますin_date。の値は、表の列にin_src_tzリストされているタイムゾーンの1つである必要があります。tznamev$timezone_names

また、タイムゾーンには複数の略語があるため、テーブルのtzabbrev列の値を単純に選択することはできません。v$timezone_names抽出を使用すると、DSTを考慮した現在の略語を取得できます。

于 2012-02-10T16:04:40.607 に答える
0

ローカル マシンとサーバーの NLS_DATE_FORMAT を比較しましたか? この違いの組み合わせと、日付が渡されるときに暗黙の変換が発生している可能性が、ここでの問題になる場合があります。

于 2012-02-09T22:26:03.503 に答える
0

これは、渡す日付パラメーターには依存しないと思います。おそらく、データベース サーバーが実行されているオペレーティング システムの設定に依存します。JDeveloper では、コンピュータ (OS) のタイム ゾーン設定から選択されている可能性があります。DB サーバーで ssh を実行し、スクリプトで最初の 2 つのクエリを実行してみてください (最初のクエリには「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 に答える