Formatting Date in JavaScript

You can use built-in JavaScript object Date to do the date formatting in JS, you can also use Locales to format your date. I want to show date in mm/dd/yyyy hh:mm Z, I used simple trick, the format I am expecting is US format, and JS frovides API to convert Date to specific local, so I passed en-US as local parameter, and using options to get the desired output.

few of the options to instantiate Date

var today = new Date(); 
var myDate = new Date(dateString);

where dateString is string representing an RFC2822 or ISO 8601 date format e.g. 12/21/2014 00:00 GMT+5:30

Converting to Local

    var myDate = new Date();
    var options = { timeZoneName: 'short', hour : '2-digit', minute : "2-digit", hour12: false};
    var dateStr = myDate.toLocaleString('en-US', options);

In options, I specified the timeZoneName which specifies if we want a short timezone name or long, hours, minutes and hour12 which specifies if the time needs to be shown in 12 hour format of 24 hours.

Other available options

  • weekday : [“narrow” | “short” | “long”]
  • era: [“narrow” | “short” | “long”]
  • year : [“2-digit” | “numeric”]
  • month : [“2-digit” | “numeric” | “narrow” | “short” | “long”]
  • day : [“2-digit” | “numeric”]
  • hour : [“2-digit” | “numeric”]
  • minute : [“2-digit” | “numeric”]
  • second : [“2-digit” | “numeric”]
  • timeZoneName : [“short” | “long”]

And if you need to format Date to more specific date format, then can use JS Date provided methods to get specific date elements like, day, year, month time etc.

   function padZero(dateArg) {
      if (dateArg < 10) {
        return '0' + dateArg;
      }
      return dateArg;
   }
   
  function formateDate(date) {
    return date.getUTCFullYear() +
        '-' + padZero(date.getUTCMonth() + 1) +
        '-' + padZero(date.getUTCDate()) +
        ' ' + padZero(date.getUTCHours()) +
        ':' + padZero(date.getUTCMinutes()) +
        ':' + padZero(date.getUTCSeconds()) ;
  }

JSFiddle Code link

Formatting Date in JavaScript

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

Date field considerations for REST with different TimeZone

REST PUT Vs POST

Actually its nothing to do with REST for PUT and POST. In general how HTTP PUT works and how POST work, is what I want to demonstrate through code.

Why REST is considered, usually we get confused while developing REST API, that when to use PUT and when to use POST for update and insert resource.

Lets start with the actual definition of these methods (copied form http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html)

POST

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.

The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.

The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.

If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).

Responses to this method are not cacheable, unless the response includes appropriate Cache-Control or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.

PUT

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a 501 (Not Implemented) response in such cases.

If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.

The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request — the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI.

Lets Go back to our REST example

Ok, now to make it more clear in REST terms, lets consider a example of Customer and Order scenario, so we have API to create/modify/get customer but for order we do have create order for customer and when we call GET /CustomerOrders API will get the customer orders.

APIs we have

GET /Customer/{custID}

PUT /Customer/{custID}

POST /Customer custID will be part of the HTTP body (to demonstrate difference between POST and PUT, otherwise for stated requirement it wont required)

POST /Order/{custID}

GET /CustomerOrders/{custID}

I have enable browser cache by adding header “Cache-Control”. so lets first see flow of PUT and GET for customer

Initial load, I called PUT /Customer/1 which placed new resource on server and then called GET /Customer/1 which returned me the customer I placed. now when I again call the GET /Customer/1 I will get the browser “Cached” instance of customer.

Now you call PUT /Customer/1 with updated values of customer, and then call GET /Customer/1, you will observer that browser makes calls to server to get new changed values. and if you add debug point or increase the wait time in you PUT, and make parallel request for GET (Ajax), then GET request will be pending till PUT is served, so browser makes cached instance of resource to stale.

In case of POST, new resource will be posted to server, but if POST request is not served, and you request for same resource using GET, cached instance will be returned. Once the post is successful and you make GET call to the resource, browser will hit to server to get new resource.

I added delay of 100 milliseconds in both PUT and POST and made request as

1) Called GET /Customer/1 multiple times to check if I am getting cached resource. Then I called PUT, and immediately called GET, and GET was pending till PUT is served. below if the screen shot which explains it.

PUTGet

2) Called GET /Customer/1 multiple times to check if I am getting cached resource. Then I called POST, and immediately called GET, and GET was served from cache. below if the screen shot which explains it.

POSTGet

So example explains all, so in our customer order case, customer should be PUT for new customer and for updating customer as we are retrieving the customer using same resource URI but for Order we used POST as we don’t have same URI for GET orders.

One More Example for PUT

You have a site which hosts different articles and documents. Client has sent request to create new documents which has title “WhyToUsePutForCreation” then your request will look like PUT /article/WhyToUsePutForCreation and once the application creates it, application will respond with 201. i.e. resource created. Now from client I can list the new document in documents list and which will be fetched by calling GET /article/WhyToUsePutForCreation

Download Code

Strange Browser Behavior : If I increase the delay in PUT method to 1000 milliseconds. First I made request to PUT /Customer/1, and immediately sent request for GET,  browser wait for PUT to get complete and after that GET request returns either cached resource or calls the server to get new resource.

I tried with different delay time, and it is not fixed behavior of Browser about, when to return the cached resource (old one) and when to request resource from server.

I am not sure if this is correct behavior, but I think its a problem with browser if I consider description of PUT.

REST PUT Vs POST

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

Testing Web Site for resposiveness and with different bandwidth

I used fiddler before to slowdown the network speed and test the web site with the slow speed. But with the new Chrome developer tool (Can be activated by pressing F12 OR Ctrl+Shift+I) you get option to emulate the screen with different mobile devices of different size. Even it has support to the notebook with touch screen.

Once the developer tool is open, just next to the “inspect element” icon, there is a small icon of mobile which enables the emulation.

DiffDevices

You can also choose the different network throttling options like, GPRS, EDGE, 3G, WiFi etc.

DiffThrottling

If you like to see if your site is mobile friendly or not, google has a very nice tool which crawl through all your pages and present the recommendation to you.

A page is eligible for the “mobile-friendly” label if it meets the following criteria as detected by Googlebot:
  • Avoids software that is not common on mobile devices, like Flash
  • Uses text that is readable without zooming
  • Sizes content to the screen so users don’t have to scroll horizontally or zoom
  • Places links far enough apart so that the correct one can be easily tapped

Link to tool https://www.google.com/webmasters/tools/mobile-friendly/

Testing Web Site for resposiveness and with different bandwidth