ユーザのタイムゾーン、日付と時刻の形式を利用する¶
項目
前提¶
- 各種設定値
設定項目 設定値 ユーザ・タイムゾーン (GMT+09:00) 日本 / 東京 システム・タイムゾーン (GMT+00:00) UTC 日付と時刻の形式 英語形式 日付(標準表示) MMM d, yyyy 日付(簡易表示) MMM d 日付(入力) yyyy/MM/dd 時刻(標準表示) h:mm a 時刻(タイムスタンプ表示) h:mm:ss a 時刻(入力) | HH:mm
テーブル定義
CREATE TABLE example_table ( user_cd VARCHAR(100) NOT NULL, update_date TIMESTAMP NOT NULL, PRIMARY KEY (user_cd) );DB アクセス
example_table テーブルの参照、更新を行うために、次のクラスが用意されていることを前提とします。example_table のレコード情報を格納するためのモデルクラスです。ExampleTableModelexample_table の参照、更新を行うクラスです。SampleService
画面から送信された日時を DB に保存する¶
画面から入力された日時をサーバ側で解析して、DB に保存するまでの流れを説明します。画面には、ユーザの日付と時刻の入力形式で次の値が入力され、サーバに送信されたとします。2012/09/19 03:46サーバ側のプログラムは以下のようになります。import java.util.Date; import jp.co.intra_mart.foundation.context.Contexts; import jp.co.intra_mart.foundation.context.model.AccountContext; import jp.co.intra_mart.foundation.i18n.datetime.format.AccountDateTimeFormatter; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatIds; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatterException; import jp.co.intra_mart.foundation.i18n.sa.sample.model.ExampleTableModel; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleService; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleServiceException; /** * サンプル */ public class SampleDateTime { /** * 画面から送信された日時を DB に保存します。 * * @param inputDate 画面から送信された日時文字列 * @throws DateTimeFormatterException * @throws SampleServiceException */ public void sample(final String inputDate) throws DateTimeFormatterException, SampleServiceException { /* * 1. 画面から送信された日時文字列を解析します。 */ final Date date = AccountDateTimeFormatter.parse(inputDate, Date.class, DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_INPUT, DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_INPUT); /* * 2. モデルを利用して、DB へ日時を保存します。 */ final ExampleTableModel model = new ExampleTableModel(); model.setUserCd(Contexts.get(AccountContext.class).getUserCd()); model.setDate(date); SampleService.getInstance().update(model); } }ユーザの入力形式に沿った日時文字列を解析するためには、AccountDateTimeFormatter を使用します。AccountDateTimeFormatter は、ログインユーザのタイムゾーンを使って解析します。DB には、システム・デフォルト・タイムゾーンに変換された日時を保存します。Date 型オブジェクトは、タイムゾーンを持たないため、DB の TIMESTAMP 型カラムには JDK のタイムゾーンに変換された日時が保存されます。JDK のタイムゾーンとシステム・デフォルト・タイムゾーンは同じです。
画面から送信された日付を DB に保存する¶
画面から入力された日付をサーバ側で解析して、DB に保存するまでの流れを説明します。注意
画面から日付のみを入力させる場合でも、次の例のように、通常は時刻まで考慮しなければなりません。(例)交通費申請の締め切り日「締め切り日」には、23時59分59秒(または、営業時間)まで、という時刻に関する意味が含まれています。例えば、本社のある日本(GMT+09:00)の9月19日が締め切り日だとすると、ホノルル(GMT-10:00)支社では、9月19日 午前5時までに交通費申請を終わらせなければなりません。画面には、ユーザの日付入力形式で次の値が入力され、サーバに送信されたとします。2012/09/19サーバ側のプログラムは以下のようになります。import java.util.Date; import jp.co.intra_mart.foundation.context.Contexts; import jp.co.intra_mart.foundation.context.model.AccountContext; import jp.co.intra_mart.foundation.i18n.datetime.format.AccountDateTimeFormatter; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatIds; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatterException; import jp.co.intra_mart.foundation.i18n.sa.sample.model.ExampleTableModel; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleService; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleServiceException; /** * サンプル */ public class SampleDateTime { /** * 画面から送信された日時を DB に保存します。 * * @param inputDate 画面から送信された日時文字列 * @throws DateTimeFormatterException * @throws SampleServiceException */ public void sample(final String inputDate) throws DateTimeFormatterException, SampleServiceException { /* * 1. 画面から送信された日時文字列を解析します。 */ final Date date = AccountDateTimeFormatter.parse(inputDate, Date.class, DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_INPUT, DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_INPUT); /* * 2. モデルを利用して、DB へ日時を保存します。 */ final ExampleTableModel model = new ExampleTableModel(); model.setUserCd(Contexts.get(AccountContext.class).getUserCd()); model.setDate(date); SampleService.getInstance().update(model); } }日付文字列の場合、時刻部分は「00:00:00」として解析されます。DB への保存は、「画面から送信された日付を DB に保存する」と同様です。
DB に保存されている日時をユーザの画面に表示する¶
DB に保存されている日時を、ユーザのタイムゾーン、日付と時刻の表示形式を使って日時文字列に整形し、画面に表示するまでの流れを説明します。サーバ側のプログラムは以下のようになります。import jp.co.intra_mart.foundation.context.Contexts; import jp.co.intra_mart.foundation.context.model.AccountContext; import jp.co.intra_mart.foundation.i18n.datetime.format.AccountDateTimeFormatter; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatIds; import jp.co.intra_mart.foundation.i18n.sa.sample.model.ExampleTableModel; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleService; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleServiceException; /** * サンプル */ public class SampleDateTimeView { /** * DB に保存されている日時をユーザの画面に表示します。 * * @return String 日時文字列 * @throws SampleServiceException */ public String sample() throws SampleServiceException { /* * 1. DB から日時を取得します。 */ final ExampleTableModel model = SampleService.getInstance().get(Contexts.get(AccountContext.class).getUserCd()); /* * 2. 日時文字列に整形します。 */ return AccountDateTimeFormatter.format(model.getDate(), DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_STANDARD, DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_STANDARD); } }DB には、システム・デフォルト・タイムゾーンに変換された日時が保存されています。ユーザの表示形式に沿った日時文字列に整形するためには、AccountDateTimeFormatter を使用します。AccountDateTimeFormatter は、ログインユーザのタイムゾーンにおける時刻を計算します。以下の結果が得られます。Sep 19, 2012 3:46 AM
DB に保存されている日付をユーザの画面に表示する¶
DB に保存されている日付を、ユーザのタイムゾーン、日付の表示形式を使って日付文字列に整形し、画面に表示するまでの流れを説明します。サーバ側のプログラムは以下のようになります。import jp.co.intra_mart.foundation.context.Contexts; import jp.co.intra_mart.foundation.context.model.AccountContext; import jp.co.intra_mart.foundation.i18n.datetime.format.AccountDateTimeFormatter; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatIds; import jp.co.intra_mart.foundation.i18n.sa.sample.model.ExampleTableModel; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleService; import jp.co.intra_mart.foundation.i18n.sa.sample.service.SampleServiceException; /** * サンプル */ public class SampleDateView { /** * DB に保存されている日付をユーザの画面に表示します。 * * @return String 日付文字列 * @throws SampleServiceException */ public String sample() throws SampleServiceException { /* * 1. DB から日時を取得します。 */ final ExampleTableModel model = SampleService.getInstance().get(Contexts.get(AccountContext.class).getUserCd()); /* * 2. 日付文字列に整形します。 */ return AccountDateTimeFormatter.format(model.getDate(), DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_STANDARD); } }次の結果が得られます。Sep 19, 2012
クライアント側で、ユーザ・タイムゾーンの今日から3日間の日付を生成し、最後の日付をサーバ側へ送信する¶
このサンプルを通して、csjs で日時データを扱う際に注意する点を理解します。
1. ユーザ・タイムゾーンの今日を取得する¶
ユーザ・タイムゾーンとは、ユーザが intra-mart Accel Platform に登録したタイムゾーンのことです。ユーザ・タイムゾーンにおける「今日」を csjs で取得するためには、intra-mart Accel Platform から提供されている ImDate を使用します。注意
ユーザ・タイムゾーンにおける「今日」の取得に、csjs の new Date を利用しないでください。csjs の new Date はクライアント OS のタイムゾーンにおける現在日時データを返しますが、ユーザ・タイムゾーンがクライアント OS のタイムゾーンと一致しているとは限りません。<script type="text/javascript" src="im_i18n/timezone/im_date_timezone.js"></script> <script type="text/javascript"> var firstDate = ImDate.now(); </script>
2. 今日から3日間の日付を生成する¶
Date に標準で用意されているメソッドを使用して構いません。var dateArray = new Array(); var date = firstDate; for (var i = 0; i < 3; i++) { dateArray[i] = date; date.setDate(date.getDate() + 1); }
3. 最後の日付をサーバ側へ送信する¶
年月日の値から日付文字列を作ります。var lastDate = dateArray[2]; var lastDateStr = lastDate.getFullYear() + "-" + (lastDate.getMonth() + 1) + "-" + lastDate.getDate();注意
ImDate.now() で生成した Date のエポックミリ秒は送信しないでください。ImDate.now() の返す Date は、ユーザ・タイムゾーンにおける「今日」の年月日時分秒を持っていますが、エポックミリ秒は正しいとは限りません。理由は、クライアント側で Date を生成しているためです。Date の持つエポックミリ秒は、クライアント OS のタイムゾーンで計算された値となり、ユーザ・タイムゾーンで計算された値と一致しない可能性があります。注意
サーバ側でユーザ・タイムゾーンの日時データを生成する場合は、Date ではなく、DateTime を使用してください。Date はシステム・デフォルトのタイムゾーンで計算するため、ユーザ・タイムゾーンとの時差を考慮して扱う必要があります。DateTime は指定されたタイムゾーンで計算することができます。jp.co.intra_mart.foundation.i18n.datetime.DateTime dateTime = new jp.co.intra_mart.foundation.i18n.datetime.DateTime(Contexts.get(AccountContext.class).getTimeZone(), 1996, Calendar.SEPTEMBER, 19, 3, 47, 0);
4. クライアント側から送信された日付文字列から Date を生成する¶
サーバ側のプログラムは以下のようになります。import java.sql.Date; import java.util.TimeZone; import javax.servlet.http.HttpServletRequest; import jp.co.intra_mart.foundation.context.Contexts; import jp.co.intra_mart.foundation.context.model.AccountContext; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatter; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatterException; /** * サンプル */ public class SampleDTF { /** * クライアント側から送信された日付文字列から Date を生成します。 * @param request リクエスト * @throws DateTimeFormatterException */ public void sample(final HttpServletRequest request) throws DateTimeFormatterException { /* * 1. クライアント側から送信された日付文字列を取得します。 */ final String inputDateStr = request.getParameter("inputDate"); /* * 2. DateTimeFormatter を使用して、日付文字列から Date を生成します。 */ final TimeZone userTimeZone = Contexts.get(AccountContext.class).getTimeZone(); final DateTimeFormatter formatter = DateTimeFormatter.withPattern("yyyy-MM-dd"); formatter.setTimeZone(userTimeZone); final Date inputDate = formatter.parse(inputDateStr, Date.class); } }日時文字列がユーザの日付と時刻の入力形式に沿っていない場合、DateTimeFormatter を使用します。DateTimeFormatter は、直接フォーマットパターンを指定することができます。DateTimeFormatter は、システム・デフォルトのタイムゾーンを使って解析を行います。ユーザ・タイムゾーンを使って解析を行う場合は、parse メソッドを実行する前に、ユーザ・タイムゾーンをセットします。