3

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

mr_urf
  • 3,303
  • 4
  • 26
  • 29
  • java.util.Date objects are not keeping any time-zone information, so what do you mean with 'it reverts to GMT and deducts 1 hour from the dates'? – jarnbjo Oct 01 '09 at 18:49
  • JAX-B uses XMLGregorianCalendar based XSDate objects as far as I can tell. Perhaps it's the parsing of the XSDate to Date which is causing the issue. I've tried to parse to a JodaTime DateTime object instead but this just gives the current date and time rather than the one that I sent. – mr_urf Oct 01 '09 at 21:13

4 Answers4

6

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.

Nathan Johns
  • 208
  • 2
  • 4
  • 8
  • Thanks. It all seems very straight forward when you put it like that! I was starting to drown in chronologies, deprecations and calendars when I was reading the JavaDocs yesterday :) If I could vote you up more than once, I would. – mr_urf Oct 02 '09 at 08:16
4

To change Time Used UTC in glassfish server:

C:\glassfish4\glassfish\bin)

asadmin create-jvm-options -Duser.timezone=UTC
asadmin restart-domain
borchvm
  • 3,533
  • 16
  • 44
  • 45
3

I solved my problem right now and with the intention of helping others developers, follow the step by step

type in your glassfish

c: \ glassfish3 \ bin \> asadmin list-jvm-options

see if the list appears

<jvm-options>-Duser.timezone=UTC</jvm-options>

case does not appear go to the domain.xml file and search for jvm-options and add the command line

<jvm-options>-Duser.timezone = Brazil / East </ jvm-options> substituting the Brazil / East timezone by country

then restart the server and be happy

Alfergon
  • 5,463
  • 6
  • 36
  • 56
Rodrigo
  • 31
  • 2
1

Locale irrelevant

Locale has nothing to do with time zone. For date-time work, a Locale determines two things: (a) human language to use in translating name of day, name of month, and such, and (b) cultural norms for issues such as period versus comma, ordering of elements (month before/after date, etc.).

Do not change default time zone

Do not change the current default time zone of the JVM as suggested on one other answer. Changing affects all code in all threads of all apps within that JVM, and does so immediately during runtime.

java.time

You are using old outmoded classes. The old date-time classes bundled with the earliest versions of Java have proven to be poorly designed, confusing, and troublesome. Avoid them. Now supplanted by the java.time framework built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

ISO 8601

Your date-time strings happen to comply with the ISO 8601 standard. This formats defined by this standard are used by default in the java.time classes when parsing/generating Strings that represent date-time values.

String input = "2009-09-17T00:00:00.000+01:00";
OffsetDateTime odt = OffsetDateTime.parse( input );

If you want the same moment on the timeline but in UTC, extract an Instant object. Best to stick to UTC and this class for much of your business logic and data-exchange and data-storage.

Instant instant = odt.toInstant();

To generate a String in ISO 8601 format, call toString.

String output = instant.toString();  // 2009-09-16T23:00:00Z

To see the same value adjusted into the wall-clock time of some time zone, apply a ZoneId to get a ZonedDateTime object. A time zone is an offset-from-UTC plus rules for handling anomalies such as Daylight Saving Time (DST).

ZoneId zoneId = ZoneId.of( "Europe/London" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Also, if you need to capture current moment in UTC:

Instant instant = Instant.now();

Adapter for JAXB

The Java Architecture for XML Binding (JAXB) may not yet support java.time types directly.

Until direct support is added, you can use an adapter for java.time types as discussed in this Answer by Blaise Doughan to the Question, Can JAXB handle java.time objects?. You might use this implementation or write your own by modeling that one or this similar one for Joda-Time library.

LocalDate

Those time-of-day values of 00:00:00 make me wonder if you are really trying to represent date-only values. In a date-only value, you do not care about time-of-day nor time zone. If that is the case, consider using the LocalDate class.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154