intra-mart Accel Platform / TERASOLUNA Global Framework Programming Guide

Version 2 2014-01-01

«  Get Message in Multi-Language Form   ::   Contents   ::   Database  »

Utilize User Time Zone and Date and Time Format

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.
ExampleTableModel
This 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:46
Server 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/19
Program 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 Format
    For the date format, please refer to Date and Time Format.
  • About Time Zone Conversion
    Character 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.
  1. bean definition xml file Setting
    mvc:message-converters is set.
  2. Controller Class Setting
    JSON is set as response.
  3. Form (Model) Class Setting
    Annotation is set to Date type property.
  4. JSP Setting
    Receive 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>

«  Get Message in Multi-Language Form   ::   Contents   ::   Database  »