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