自動タイムゾーンをOFFにする
APIの呼び出しでタイムゾーンを設定するので、自動タイムゾーンはOFFにします。グローバリゼーション属性の設定になります。
この画面へたどり着くパスはいくつかあります。ひとつ目のパスは、アプリケーション・プロパティの編集です。
共有コンポーネントからもたどり着くことができます。アプリケーション・ロジックに含まれるアプリケーション定義属性を開いてグローバリゼーションを選ぶ、または、グローバリゼーションに含まれるグローバリゼーション属性を選びます。
空白の非モーダル・ダイアログのページを作成する
タイムゾーンをユーザーのプリファレンスのひとつとして設定するページを作成します。ページの作成を開始します。
空白ページをクリックします。
ページ番号を7、名前をプリファレンス、ページ・モードは非モーダル・ダイアログとします。オプションとして作成できる静的コンテンツ・リージョンのリージョン1をプリファレンスとして作成します。次へ進みます。
このページとナビゲーション・メニュー・エントリを関連付けないを選び次へ進みます。
作成されるページの確認画面が表示されるので、終了をクリックします。
これで、非モーダル・ダイアログのページが作成されました。
タイムゾーンを設定するページ・アイテムを作成する
名前をP7_TIMEZONE、タイプは選択リスト(タイムゾーン名の一覧から選択します)、ラベルをタイムゾーンとし、選択時のページ・アクションはデフォルトのNoneのままにします。選択時のアクションは後に動的アクションで設定します。選択リストとなるLOVは、タイプをSQL問合わせとして、以下のSQLを設定します。
select tzname as d, tzname as r
from v$timezone_names
group by tzname
order by tzname
さらに、詳細の保存されていない変更の警告を無視にします。値の変更は動的アクションによって行われるため、ページ上の変更がデータベースに反映されていない、ということは発生しません。ソースの設定ですが、タイプをプリファレンスとし、プリファレンス名はMY_TIMEZONEとします。使用はセッション・ステートの既存の値を常に置換、セッション・ステートの保持はリクエストごと(メモリーのみ)とします。
次に、このページ・アイテムの値が変更されたときに実行される動的アクションを定義します。動的アクションのタイミングは、イベントとしては変更、選択タイプはアイテム、そしてアイテムはP7_TIMEZONEになります。これでP7_TIMEZONEが変更されたときに、アクションが実行されます。
実行されるアクションとして、以下のPL/SQLコードを指定します。APEX_UTIL.SET_SESSION_TIME_ZONEを呼び出すことで、タイムゾーンを設定しています。また、MY_TIMEZONEというプレファレンスに、設定したタイムゾーンを記憶することで新たにサインインした際に、設定済みのタイムゾーンを回復できるようにします。
begin
apex_util.set_session_time_zone(:P7_TIMEZONE);
apex_util.set_preference('MY_TIMEZONE', :P7_TIMEZONE, :APP_USER);
end;
アクションはPL/SQLコードの実行、送信するアイテムとしてP7_TIMEZONEを含めます。
最後にダイアログをクローズするためのボタンを追加します。ボタンを作成し、動作のアクションは動的アクションで定義します。
動的アクションを作成し、ボタンがクリックされたときに、アクションが実行される設定を行います。
実行されるアクションは、ダイアログを閉じるです。
これで、タイムゾーンを設定する非モーダル・ページは完成です。
ナビゲーション・バーへプレファレンスを開くメニューを追加する
共有コンポーネントのナビゲーション・バー・リストを開きます。
デスクトップ・ナビゲーション・バーを開きます。
&APP_USER.つまりサインインしたユーザー名をクリックしたときに表示されるメニューとして、プリファレンスのエントリを作成します。エントリの作成をクリックします。
追加したメニューがリストに表示されます。
メニューについてはこれで完了です。
サインイン時にプリファレンスからタイムゾーンを回復する
アプリケーション・プロセスとして、以下のコードを認証後に実行することで、プリファレンスMY_TIMEZONEからタイムゾーンの設定を回復します。
declare
l_my_tz varchar2(40);
begin
l_my_tz := apex_util.get_preference('MY_TIMEZONE', :APP_USER);
if l_my_tz is not null then
apex_util.set_session_time_zone(l_my_tz);
end if;
end;
共有コンポーネントのアプリケーション・プロセスを開きます。
アプリケーション・プロセスの一覧画面から、作成を実行します。
名前をタイムゾーンの回復、ポイントは認証後とします。次へ進みます。
最初に示したコードを入力して次へ進みます。
条件タイプは無指定にして(- 条件タイプの選択 - という表示のままにしておく)、プロセスの作成をクリックします。
登録したプロセスがリストの表示されます。
これで、サインイン時にプリファレンスとして設定されているタイムゾーンが回復します。
動作確認をする
アプリケーションを実行して、Datetimesレポートを開きます。その後、右上のユーザー名をクリックし、追加したプリファレンスが含まれるメニューを表示させます。
開いたページでタイムゾーンとしてUS/Easternを選びます。ダイアログは開いたままで構いません。
Datetimesレポートに戻り、変更したタイムゾーンを反映させるため、ブラウザの機能を使ってページの再読み込み(リロード)を行います。タイムゾーン・オフセットがUS/Easternになっていることを確認します。
タイムゾーン・オフセットが-04:00のときのTSLTZ型の表示と比較してみましょう。
ニューヨーク冬以外の時刻はタイムゾーン・オフセットが-04:00でもUS/Easternでも同じ表示です。ニューヨーク冬のみ表示が異なり、TSTZ型の表示と一致するタイムゾーン・オフセットUS/Easternが、オフセットを-05:00と扱っています。つまり夏時間は適切に扱われています。
タイムゾーンがUS/Easternの状態で、2020/12/21 00:00を追加します。ニューヨーク冬2とします。
今度はTSLTZ型、TSTZ型の双方とも、2020/12/21 00:00として時刻が表示されます。
サインアウトして再度サインインしたときに、タイムゾーンがきちんと回復するかどうか試してみてください。回復するはずです。
夏時間を扱う場合は夏時間に対応したタイムゾーンを設定する必要がある、というのが今回のポイントです。