mr_urf mr_urf - 4 months ago 27
Java Question

Wrong timezone being used in Java web service

I have a JAX-B java web service which I'm using to update a database. Each row in the table that I'm updating is represented by an object similar to below: -

public class Item {
private String id;
private Date startDate;
private Date endDate;

public Item() { }

...

}


This class is being instantiated in a separate program and then passed via SOAP in a message similar to below: -

...

<item>
<id>D001IAAC030</id>
<startDate>2009-09-17T00:00:00.000+01:00</startDate>
<endDate>2009-10-01T00:00:00.000+01:00</endDate>
</item>

...


As you can see, due to BST the UTC time has a +01:00 offset. However, when the object is marshalled on the server (which is on my local machine as well), it reverts to GMT and deducts 1 hour from the dates.

Can you tell me how I can either: -


  1. Set my Glassfish server to right locale so that the dates are recognised as being BST.

  2. Tell me how I can intercept the marshalling at the web service end so that I can set the timezone myself before the date is set.



TIA,

Urf

Answer

You just need to remember that a Date object (always) stores date/time as milliseconds since epoch in the UTC/GMT time zone. What trips people up is that the Date.toString() method returns a text representation in the JVM's default time zone (via an internal Calendar object). (Take a look at JDK source code.)

So for instance on my machine

Date now = new Date();
System.out.println(now.toString());
System.out.println(now.getTime())

will give

Fri Oct 02 06:56:24 EST 2009
1254430584531

The milliseconds number being the actual milliseconds since epoch in the GMT/UTC time zone.

You should always use Date formatters or Calendar instances when manipulating/using Date objects. For example:

Date now = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:MM:ss zzz yyyy");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(now.toString());
System.out.println(sdf.format(now));

gives

Fri Oct 02 06:56:24 EST 2009
Thu Oct 01 20:56:24 UTC 2009

In summary: Always treat a Date object as data only, milliseconds since epoch. (Don't use any of the Deprecated methods, and don't use toString() unless you understand what it is displaying.) To display, format, convert (add subtract time etc) date/time always use a Calendar instance or DateFormat implementation and it is hard to go wrong.

As the Javadoc says for Date:

'Prior to JDK 1.1, the class Date had two additional functions. It allowed the interpretation of dates as year, month, day, hour, minute, and second values. It also allowed the formatting and parsing of date strings. Unfortunately, the API for these functions was not amenable to internationalization. As of JDK 1.1, the Calendar class should be used to convert between dates and time fields and the DateFormat class should be used to format and parse date strings. The corresponding methods in Date are deprecated.'

Experiment for yourself with Date's, Calendars and Formatters and read the Javadoc and it will become a little clearer.

For the first part of your question you shouldn't need to set the time zone of your Glassfish server to accommodate your data. If you want to store time zone data with your data/time values then use Calendar rather than Date in your objects. Or as I usually do, everything is stored as UTC time (in db and Date instances in objects) and time zones are only used when data is displayed/outputted or parsed. So when your data is received parse it with a DateFormat or equivalent with time zone set to +01:00 (it may pick that up from the time string automatically if it has the time zone attached as you example shows).

I don't know specifically about the second part of your question but if the implementation of your web-service end handles Dates correctly and parses them correctly it should handle this without your intervention.