Date field considerations for REST with different TimeZone

I can see two different scenarios of using the Date field with consideration of TimeZone, one is when the user enters date and you need to display the same date on screen, what I mean is with same TimeZone, and other one is the Date is entered by Admin kind of user from his TmeZone and you need to display the the saved Date with users TimeZone.

Simple work flow is

1) Select the Date and time from UI with TimeZone option (You can ignore TimeZone if you don’t want to display it to user, and while submitting or making REST request you can add the TimeZone details)

2) On server deserialize the date to UTC to persist the date filed

3) When GET request is made to the resource which has Date field, retrieve date from where you persisted, return it with the TimeZone details.

4) Client side, create Date instance from passed in date string, and JavaScript Date object will by default convert it to client specific TmeZone. You can use Date object and display your date in desired format.

In your bean filed annotate it as

	@JsonSerialize(using=JsonDateSerializer.class)
	public Date getJoinDate() {
		return joinDate;
	}

	@JsonDeserialize(using=JsonDateDeserializer.class)
	public void setJoinDate(Date joinDate) {
		this.joinDate = joinDate;
	}

Java Code to Deserialize JSON to Date

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
 
@Component
public class JsonDateDeserializer extends JsonDeserializer<Date> {
 
 private static final SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy hh:mm ZZ");
 
 @Override
 public Date deserialize(JsonParser jp, DeserializationContext ctxt)
 throws IOException, JsonProcessingException {
 
 ObjectCodec oc = jp.getCodec();
 JsonNode node = oc.readTree(jp);
 
 String dateString = node.asText();
 
 Date joinDate;
 try {
 joinDate = dateFormat.parse(dateString);
 } catch (ParseException e) {
 throw new JsonParseException(e.getMessage(), JsonLocation.NA);
 }
 
 return joinDate;
 }
 
}

in above screen I used final static for SimpleDateFormat, SimpleDateFormat class is not thread safe, and I FastDateFormat which is good alternative to SimpleDateFormat which is used in serialize code snippet listed below. You can also use JodaTime api for date and calendar manipulations, ideally you should not use SimpleDateFormat and instead should move to Apache Commons-lang date implementations and if you need full support of parsing and formatting then use JodaTime library.

To serialize from Date to JSON

import java.io.IOException;
import java.util.Date;
import java.util.TimeZone;
 
import org.apache.commons.lang.time.FastDateFormat;
import org.springframework.stereotype.Component;
 
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
 
@Component
public class JsonDateSerializer extends JsonSerializer<Date>{
 
 private FastDateFormat fastDateFormat = FastDateFormat.getInstance("MM/dd/yyyy hh:mm Z", TimeZone.getTimeZone("UTC"));
 
 @Override
 public void serialize(Date date, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {
 
 String formattedDate = fastDateFormat.format(date);
 gen.writeString(formattedDate);
 }
}

In above code I have created the FastDateFormat instance with UTC TimeZone, and to add timezone details I added “Z”, which will add the timezone details in RFC822 format i.e. +0530.

In my example I displayed Date as it is default get converted to string by using JavaScript built-in object Date.

If you want to display the Date (particularly with time) at client as per Locale and with very specific format, will suggest to do the formatting on Java side based on user locale and timezone, as formatting Date in JavaScript to a specific format is tricky. JavaScript has good support for formatting date to Local but if you want some different format then it become tricky, e.g. with en-US the date time will displayed as 12/21/2014, 12:00 AM GMT+5:30, and now if you want to remove comma and different timezone format then it become tricky.

form more details : JavaScipt Date Tutorial

Advertisements
Date field considerations for REST with different TimeZone

Spring’s Device Detection (Spring Boot) Vs WURFL Device detection

I liked the Spring Boot idea very much, very impressive. Excellent use of Embedded servers, auto configs and the best thing with less code you can complete the functionality.

When I was going through the basic guides of Spring boot, I tried the Device Detection guide, which detects the the device from which the request is made, its basic implementation which tells you if request is made form Mobile, Tab or PC.

Spring Device has used the “User-Agent”, “x-wap-profile”, “Accept” HTTP headers to detect the device type, if all of the listed headers fails to identify the device type, in the last code iterate through all the headers to see if the request is from “Opera Mini” browser, which mostly used by many mobile users.

Spring Device has used basic algorithm used in WordPress’s Mobile pack, which works for large number of mobile browsers.

If you need to know full capabilities of the phone, like OS type, touch screen support, browser type, XHTML-MP supprted or not etc then WURFL API is a good option.

Only thing is WURFL API is not updated for the Spring Boot and uses old version of commons-lang and other dependent libraries. As source code is provided I modified a bit and I was able to use the WURFL API for device detection.

WURFL has commercial license available and also has cloud based service if you want to try.

You can download the code from the WURFL’s repository, to create GeneralWURFLEngine class as spring componant I added @Component annotation

@Component(value="WURFLEngine")public class GeneralWURFLEngine implements WURFLEngine, WurflWebConstants {

and it dosent have default constructor, I added one with following lines, where wurfl.zip file has the XML file which has all data related to mobile devices.

 static URL filePath = GeneralWURFLEngine.class.getClassLoader().getResource("wurfl.zip");
  
 public GeneralWURFLEngine() {
 this(new XMLResource(filePath.getPath()));
 }

and when I started the Spring Boot Application, I added the package of the GeneralWURFLEngine class to component scan path, and one more major change, as Maven repository for WURFL is only available if you license, I added jar in /lib folder.

Below is the code changed made to Spring Boot guide for device detection.

package com.ykshinde.controller;
 
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
 
import net.sourceforge.wurfl.core.WURFLEngine;
 
import org.springframework.mobile.device.Device;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
@Controller
public class DeviceDetectionController {
 
    @Resource(name="WURFLEngine")
    WURFLEngine engine;
     
    @RequestMapping("/detect-device")
    public @ResponseBody String detectDevice(Device device, HttpServletRequest request) {
         
        net.sourceforge.wurfl.core.Device device2 = engine.getDeviceForRequest(request);
         
        StringBuffer deviceCapabilities = new StringBuffer();
 
        deviceCapabilities.append(" DEVICE_ID : ").append(device2.getId()).append("<br>")
        .append(" DEVICE_OS : ").append(device2.getCapability("device_os")).append("<br>")
        .append(" DEVICE_OS_VERSION : ").append(device2.getCapability("device_os_version")).append("<br>")
        .append(" IS_TABLET : ").append(device2.getCapability("is_tablet")).append("<br>")
        .append(" IS_WIRELESS_DEVICE : ").append(device2.getCapability("is_wireless_device")).append("<br>")
        .append(" MOBILE_BROWSER : ").append(device2.getCapability("mobile_browser")).append("<br>")
        .append(" MOBILE_BROWSER_VERSION : ").append(device2.getCapability("mobile_browser_version")).append("<br>")
        .append(" POINTING_METHOD : ").append(device2.getCapability("pointing_method")).append("<br>")
        .append(" PREFERRED_MARKUP : ").append(device2.getCapability("preferred_markup")).append("<br>")
        .append(" RESOLUTION_HEIGHT : ").append(device2.getCapability("resolution_height")).append("<br>")
        .append(" RESOLUTION_WIDTH : ").append(device2.getCapability("resolution_width")).append("<br>")
        .append(" UX_FULL_DESKTOP : ").append(device2.getCapability("ux_full_desktop")).append("<br>")
        .append(" XHTML_SUPPORT_LEVEL : ").append(device2.getCapability("xhtml_support_level")).append("<br>");
         
         
        String deviceType = "unknown";
        if (device.isNormal()) {
            deviceType = "normal";
        } else if (device.isMobile()) {
            deviceType = "mobile";
        } else if (device.isTablet()) {
            deviceType = "tablet";
        }
         
        deviceCapabilities.append(" DEVICE TYPE (SPRING BOOT) : ").append(deviceType);
         
        return deviceCapabilities.toString();
    }
 
}

And below is the response displayed when request emulated as from “Samsung Tab ”


DEVICE_ID : samsung_galaxy_tab_ver1_subschi800
DEVICE_OS : Android
DEVICE_OS_VERSION : 2.2
IS_TABLET : true
IS_WIRELESS_DEVICE : true
MOBILE_BROWSER : Android Webkit
MOBILE_BROWSER_VERSION :
POINTING_METHOD : touchscreen
PREFERRED_MARKUP : html_web_4_0
RESOLUTION_HEIGHT : 1024
RESOLUTION_WIDTH : 600
UX_FULL_DESKTOP : false
XHTML_SUPPORT_LEVEL : 4
DEVICE TYPE (SPRING BOOT) : mobile

NOTE : If you are going to use WURFL Api commercially, please do check the licensing part of it.

 Download Code

Spring’s Device Detection (Spring Boot) Vs WURFL Device detection