Utilize User Time Zone and Date and Time Format¶
Topics
- Assumptions
- Store Date and Time sent from the Screen to DB
- Store Date sent from the Screen to DB
- Display Date and Time stored on DB to User Screen
- Display Date stored on DB to User Screen
- Create 3-days dates from today of user time zone on the client side, and send the last date to the server side.
- Receive character string sent from the client side as Date using @AccountDateFormat annotation.
- Receive character string sent from the client side as Date using Data binding.
- Set JSON to the response and set the format of Date type property for return.
Assumptions¶
- Various Setting Values
Setting Items Setting Value User Time Zone (GMT+09:00) Japan/Tokyo System Time Zone (GMT+00:00) UTC Date and Time Format English Form Date (Standard Display) MMM d, yyyy Date (Simple Display) MMM d Date (Input) yyyy/MM/dd Time (Standard Display) h:mm a Time (Time Stamp Display) h:mm:ss a Time (Input) HH:mm
Table Definition
CREATE TABLE example_table ( user_cd VARCHAR(100) NOT NULL, update_date TIMESTAMP NOT NULL, PRIMARY KEY (user_cd) );DB Access
example_table It is assumed that the following classes are made ready for the access/update of the tables.This is a model class that stores record information of example_table.ExampleTableModelThis is a class that refers to and updates example_table.SampleService
Store Date and Time sent from the Screen to DB¶
This section describes the flow in which date and time entered on the screen is analyzed at the server side and stored into DB.Please assume that the value below is entered in user’s date and time input format, and sent to the server.2012/09/19 03:46Server side program will be as follows.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; /** * Sample */ public class SampleDateTime { /** * Store date and time sent by the screen to DB. * * @param inputDate Date and time character string sent by the screen * @throws DateTimeFormatterException * @throws SampleServiceException */ public void sample(final String inputDate) throws DateTimeFormatterException, SampleServiceException { /* * 1. Analyze date and time character string sent by the screen. */ final Date date = AccountDateTimeFormatter.parse(inputDate, Date.class, DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_INPUT, DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_INPUT,); /* * 2. Store date and time to DB utilizing the model. */ final ExampleTableModel model = new ExampleTableModel(); model.setUserCd(Contexts.get(AccountContext.class).getUserCd()); model.setDate(date); SampleService.getInstance().update(model); } }AccountDateTimeFormatter is used to analyze the date and time character string in user’s input format.AccountDateTimeFormatter will use log-in user’s time zone for analysis.Date and time which are converted to the system default time zone are stored to DB.Since Date type object does not have a time zone, date and time which are converted to the time zone of JDK are stored to the TIMESTAMP type column of DB.Time zone of JDK and the system default time zone are the same.
Store Date sent from the Screen to DB¶
This section describes the flow in which the date entered on the screen is analyzed on the server side and stored into DB.Warning
When only the date needs to be entered on the screen, the time should usually be considered as well like the example below.(example) Deadline Date of Transportation Expense Application[Deadline Date] usually implies the time until 23:59:59 (or until the end of office hour).For example, if the deadline date in the HQ location Japan (GMT+09:00) is September 19, transporation expense application at the Honolulu brnch (GMT-10:00) should be completed before 5 am on September 19.Suppose that the value below is entered on the screen in user’s date input format, and is sent to the server.2012/09/19Program at the server side will be as follows.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; /** * Sample */ public class SampleDateTime { /** * Store date and time sent by the screen to DB. * * @param inputDate Date and time character string sent by the screen * @throws DateTimeFormatterException * @throws SampleServiceException */ public void sample(final String inputDate) throws DateTimeFormatterException, SampleServiceException { /* * 1. Analyze date and time character string sent by the screen. */ final Date date = AccountDateTimeFormatter.parse(inputDate, Date.class, DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_INPUT, DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_INPUT,); /* * 2. Store date and time to DB utilizing the model. */ final ExampleTableModel model = new ExampleTableModel(); model.setUserCd(Contexts.get(AccountContext.class).getUserCd()); model.setDate(date); SampleService.getInstance().update(model); } }In case it is a date character string, analysis is made with the time part as [00:00:00].Storing to DB is similar to [Date sent from the screen is stored into DB].
Display Date and Time stored on DB to User Screen¶
This section describes the flow in which date and time stored in DB are reshaped into the date and time character string using user’s time zone and date and time format,and are displayed on the screen.Program on the server side will be as follows.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 { /** * Display date and time saved in DB on the user screen. * * @return String Date and time character string * @throws SampleServiceException */ public String sample() throws SampleServiceException { /* * 1. Get date and time from DB. */ final ExampleTableModel model = SampleService.getInstance().get(Contexts.get(AccountContext.class).getUserCd()); /* * 2. Shape into date and time character string. */ return AccountDateTimeFormatter.format(model.getDate(), DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_STANDARD, DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_STANDARD); } }Date and time converted to the system default time zone are stored into DB.AccountDateTimeFormatter is used to reshape date and time to the character string in user’s format.AccountDateTimeFormatter computes the time in log-in user’s time zone.The result below will be obtained.Sep 19, 2012 3:46 AM
Display Date stored on DB to User Screen¶
This section describes the flow in which the date stored in DB is reshaped into the date character string in user’s time zone and date format, and is displayed on the screen.Program on the server side is as follows.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; /** * Sample */ public class SampleDateView { /** * Display the date saved in DB on the user screen. * * @return String Date character string * @throws SampleServiceException */ public String sample() throws SampleServiceException { /* * 1. Get date and time from DB. */ final ExampleTableModel model = SampleService.getInstance().get(Contexts.get(AccountContext.class).getUserCd()); /* * 2. Shape into date character string. */ return AccountDateTimeFormatter.format(model.getDate(), DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_STANDARD); } }The result below will be obtained.Sep 19, 2012
Create 3-days dates from today of user time zone on the client side, and send the last date to the server side.¶
Items for attention when handling date and time data in csjs are shown in this sample.
1. Get today of user time zone.¶
User time zone is the time zone user has registered in intra-mart Accel Platform.ImDate provided by intra-mart Accel Platform is used to obatin user time zone’s [Today] by csjs.Warning
Please do not use new Date of csjs to obtain [Today] in user time zone.new Date of csjs returns the current date and time data in the time zone of client OS, but user time zone does not necessarily match with the time zone of client OS.<script type="text/javascript" src="im_i18n/timezone/im_date_timezone.js"></script> <script type="text/javascript"> var firstDate = ImDate.now(); </script>
2. Generate 3-days dates from Today¶
You cn use the method which is provided as standard by Date.var dateArray = new Array(); var date = firstDate; for (var i = 0; i < 3; i++) { dateArray[i] = date; date.setDate(date.getDate() + 1); }
3. Send the last date to the server side¶
Create date character string from the year-month-day value.var lastDate = dateArray[2]; var lastDateStr = lastDate.getFullYear() + "-" + (lastDate.getMonth() + 1) + "-" + lastDate.getDate();Warning
Please do not send the epoch milliseconds of Date generated by ImDate.now().Date which is returned by ImDate.now() has year-month-day-hour-minute-second of [Today] in user time zone, but epoch milliseconds may not be always correct.This is because Date is created by the client side.Epoch milliseconds of Date are the value computed in the time zone of client OS, and may not match with the value computed in user time zone.Warning
In case date and time data of user time zone is generated on the server side, please use DateTime instead of Date.Date is computed in the system default time zone, and therefore should be handled with the time difference from the user time zone in consideration.DateTime can be computed in the specified time zone.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. Create Date from the date character string sent from the client side¶
Program on the server side will be as follows.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; /** * Sample */ public class SampleDTF { /** * Generate Date from the date character string sent by the client side. * @param request Request * @throws DateTimeFormatterException */ public void sample(final HttpServletRequest request) throws DateTimeFormatterException { /* * 1. Get date character string sent by the client side. */ final String inputDateStr = request.getParameter("inputDate"); /* * 2. Generate Date from the date character string utilizing DateTimeFormatter. */ 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); } }If the date and time character string does not conform to user’s date and time input format, DateTimeFormatter will be used.In DateTimeFormatter you can directly specify the format pattern.DateTimeFormatter does the analysis using the system default time zone.In case the analysis is made using user time zone, user time zone should be set before executing the parse method.
Receive character string sent from the client side as Date using @AccountDateFormat annotation.¶
Date, date and time, and time character string entered on the screen are bound to the Date type field.Annotations that support date, date and time, and time are as follows.
Pattern Annotation Format Time Zone Conversion (default value) Date @AccountDateFormat Date(Input) None Date and Time @AccountDateTimeFormat Date(Input) Time(Input) Yes Time @AccountTimeFormat Time(Input) None
About FormatFor the date format, please refer to Date and Time Format. About Time Zone ConversionCharacter string entered is assumed to be the date and time in the account time zone, and is made to the system time zone when it is set to the Date type property on the server side. In case there is no time zone conversion, both the entered character string and Date type property on the server side have the value in the system time zone.Example below shows that the character string entered on the screen is assumed to be in the account time zone, and is set to Date type property.import java.util.Date; import jp.co.intra_mart.framework.extension.spring.format.annotation.AccountDateFormat; import jp.co.intra_mart.framework.extension.spring.format.annotation.AccountDateTimeFormat; import jp.co.intra_mart.framework.extension.spring.format.annotation.AccountTimeFormat; public class SampleForm { // System timezone is set to JST here. // Bind the request character string of date format to Date type property. // (String) 2000/01/01 is made to (Date) 2000/01/01 00:00:00 JST. // Default is no conversion of time zone. @AccountDateFormat private Date date; // Request character string of date and time format is bound to Date type property. // If the account time zone is GMT, system time zone is converted to JST(+9), and so // (String) 2000/01/01 00:00 is made to (Date) 2000/01/01 09:00:00 JST. @AccountDateTimeFormat private Date datetime; // Request character string of time format is bound to Date type property. // (String) 01:00 is made to (Date) 1970/01/01 01:00:00 JST. // Default is no conversion of time zone. @AccountTimeFormat private Date time; // If the setting is with timezone conversion in date format // (String) 2000/01/01 is made to (Date) 2000/01/01 09:00:00 JST. @AccountDateFormat(convertTimeZone = true) private Date dateTimezone; // getter, setter ... }Note
In case format conversion fails, resolution of error message code conforms to the Spring Framework specifications.
Receive character string sent from the client side as Date using Data binding.¶
Create the method which sets @InitBinder in Controller class, and register data bind definition.Shown below is the example of data bind using @InitBinder.import java.util.Date; public class SampleForm { private Date date; private Date datetime; private Date time; // getter, setter ... }import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import jp.co.intra_mart.foundation.i18n.datetime.format.AccountDateTimeFormatter; import jp.co.intra_mart.foundation.i18n.datetime.format.DateTimeFormatIds; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("sample/tgfw/datetime") public class DateTimeController { @RequestMapping("register") public String register(SampleForm form, BindingResult result) { // Register, and re-display Input Screen // Registration Process etc... return "sample/tgfw/datetime/input.jsp"; } @InitBinder public void initBinder(final WebDataBinder binder) { // Set data bind for the property "date" // Get "Date(Input)" format pattern. final String datePattern = AccountDateTimeFormatter.getPattern(DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_INPUT); // Generate DateFormat. final DateFormat dateFormat = new SimpleDateFormat(datePattern); // Register data bind for the property "date". binder.registerCustomEditor(Date.class, "date", new CustomDateEditor(dateFormat, true)); // Set data bind for the property "datetime" final String datetimePattern = AccountDateTimeFormatter.getPattern(DateTimeFormatIds.IM_DATETIME_FORMAT_DATE_INPUT, DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_INPUT); final DateFormat datetimeFormat = new SimpleDateFormat(datetimePattern); binder.registerCustomEditor(Date.class, "datetime", new CustomDateEditor(datetimeFormat, true)); // Data bind setting for the property "time" final String timePattern = AccountDateTimeFormatter.getPattern(DateTimeFormatIds.IM_DATETIME_FORMAT_TIME_INPUT); final DateFormat timeFormat = new SimpleDateFormat(timePattern); binder.registerCustomEditor(Date.class, "time", new CustomDateEditor(timeFormat, true)); } }Character string entered on the screen is set to the Date type field of date, datetime, and time.In this example there is no time zone conversion. Both the entered character string and Date type property on the server side have the value in system time zone.
Set JSON to the response and set the format of Date type property for return.¶
In Spring Framework MVC, Jackson is used to convert Java object to JSON when the response is set to JSON and returned.In Jackson, Date type property is generated in epoch milliseconds as default.The method of returning it as character string converted in the account date format is shown.Setting of Jackson is made as follows to allow format of Date type property at JSON output time to be specified.By doing this, you can set @AccountDateFormat annotation to (Form) Model Class, and can format and output the date.
bean definition xml file Settingmvc:message-converters is set. Controller Class SettingJSON is set as response. Form (Model) Class SettingAnnotation is set to Date type property. JSP SettingReceive json data on JSP side.
1. bean definition xml file Setting¶
Add mvc:message-converters tag to mvc:annotation-driven tag of applicationContext-im_tgfw_web.xml.Set MappingJacksonHttpMessageConverter to Message converter, and set AccountDateObjectMapper to its objectMapper property.Annotation will function by AccountDateObjectMapper.<mvc:annotation-driven conversion-service="conversionService"> <!-- omitted --> <!-- jackson message converter --> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="objectMapper"> <bean class="jp.co.intra_mart.framework.extension.spring.http.converter.json.AccountDateObjectMapper" /> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
2. Controller Class Setting¶
Follow SpringFramework MVC, and make the setting to set JSON to response.In this example, class to put JSON to the return value of method is defined, and the @ResponseBody annotation is set to the method.@Controller @RequestMapping("path/to") public class SampleController { @RequestMapping("sample") @ResponseBody public SampleModel callJsonSample() { SampleModel sampleModel = new SampleModel(); // Process to set the value to sampleModel return sampleModel; } }
3. Form (Model) Class Setting¶
On an as required basis, @AccountDateFormat annotation is set to Date type property.import java.util.Date; import jp.co.intra_mart.framework.extension.spring.format.annotation.AccountDateFormat; public class SampleModel { // without annotation private Date date; // example of setting AccountDateFormat annotation @AccountDateFormat private Date dateDefault; // example of setting format type to SIMPLE @AccountDateFormat(type = AccountDateFormat.TYPE.SIMPLE) private Date dateSimple; // example of setting AccountDateTimeFormat annotation @AccountDateTimeFormat private Date datetimeDefault; // setter & getter }
4. JSP Setting¶
Example of receiving JSON data by Ajax is shown.<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="imui" uri="http://www.intra-mart.co.jp/taglib/imui"%> <imui:head> <title>sample</title> <script type="text/javascript"> (function ($) { $(document).ready(function () { $('#link').on('click', function () { $.ajax({ dataType : 'json', url : '<c:url value="path/to/sample"/>', type :'GET', success : function (data, textStatus, jqXHR) { // example of processing received data (data) $('#date').val(data.date); $('#dateDefault').val(data.dateDefault); $('#dateSimple').val(data.dateSimple); $('#datetimeDefault').val(data.datetimeDefault); } }); }); }); })(jQuery); </script> </imui:head> <div class="imui-title"> <h1>json - index page</h1> </div> <div class="imui-form-container"> <a href="javascript:void(0);" id="link">fetch data</a> <ul> <li>without annotation - displayed in epoch milliseconds<br/><input type="text" id="date" name="date" value=""></li> <li>@AccountDateFormat - displayed in yyyy/MM/dd format<br/><input type="text" id="dateDefault" name="dateDefault" value=""></li> <li>@AccountDateFormat(type = SIMPLE) - displayed in MM/dd format<br/><input type="text" id="dateSimple" name="dateSimple" value=""></li> <li>@AccountDateTimeForma - displayed in yyyy/MM/dd HH:mm format<br/><input type="text" id="datetimeDefault" name="datetimeDefault" value=""></li> </ul> </div>