Не можете получить информацию о часовом поясе при использовании mod_plsql? - PullRequest
0 голосов
/ 10 февраля 2012

Я написал функцию для преобразования даты в метку времени 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?

Ответы [ 3 ]

0 голосов
/ 10 февраля 2012

Вы сравнивали NLS_DATE_FORMAT на вашем локальном компьютере и сервере? Вы можете обнаружить, что комбинация различий в этом и вероятность того, что в момент передачи даты происходит непредвиденное преобразование, могут быть вашей проблемой.

0 голосов
/ 10 февраля 2012

Функция, как написано, не работает, если сеанс, вызывающий ее, не имеет информации о часовом поясе. Поэтому вам необходимо явно указать исходный часовой пояс. Следующая функция решает эту проблему (и исправляет тип возвращаемого значения):

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.

0 голосов
/ 10 февраля 2012

Полагаю, это не зависит от параметра даты, который вы передаете. Вероятно, это зависит от настроек операционной системы, в которой работает сервер базы данных. В JDeveloper это возможно из настроек часового пояса вашего компьютера (ОС). Попробуйте выполнить 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.
...