tags:

views:

855

answers:

6

I have a database field that contains a raw date field (stored as character data), such as

Friday, September 26, 2008 8:30 PM Eastern Daylight Time

I can parse this as a Date easily, with SimpleDateFormat

DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
Date scheduledDate = dbFormatter.parse(rawDate);

What I'd like to do is extract a TimeZone object from this string. The default TimeZone in the JVM that this application runs in is GMT, so I can't use .getTimezoneOffset() from the Date parsed above (because it will return the default TimeZone).

Besides tokenizing the raw string and finding the start position of the Timezone string (since I know the format will always be EEEE, MMMM dd, yyyy hh:mm aa zzzz) is there a way using the DateFormat/SimpleDateFormat/Date/Calendar API to extract a TimeZone object - which will have the same TimeZone as the String I've parsed apart with DateFormat.parse()?

One thing that bugs me about Date vs Calendar in the Java API is that Calendar is supposed to replace Date in all places... but then they decided, oh hey let's still use Date's in the DateFormat classes.

A: 

Well as a partial solution you could use a RegEx match to get the timezone since you will always have the same text before it. AM or PM.

I don't know enough about Java timezones to get you the last part of it.

Mitchel Sellers
+1  A: 

I found that the following:

        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        Date scheduledDate = dbFormatter.parse("Friday, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(scheduledDate);
        System.out.println(dbFormatter.format(scheduledDate));
        TimeZone tz = dbFormatter.getTimeZone();
        System.out.println(tz.getDisplayName());
        dbFormatter.setTimeZone(TimeZone.getTimeZone("America/Chicago"));
        System.out.println(dbFormatter.format(scheduledDate));

Produces the following:

Fri Sep 26 20:30:00 CDT 2008
Friday, September 26, 2008 08:30 PM Eastern Standard Time
Eastern Standard Time
Friday, September 26, 2008 08:30 PM Central Daylight Time

I actually found this to be somewhat surprising. But, I guess that shows that the answer to you question is to simply call getTimeZone on the formatter after you've parsed.

Edit: The above was run with Sun's JDK 1.6.

Ed Thomas
I was also surprised by this and have run into issues with TimeZone sliding due to Date instantiation before.
18Rabbit
Just curious - what is the result of TimeZone.getDefault() on your machine?
matt b
A: 

The main difference between Date and Calendar is, that Date is just a value object with no methods to modify it. So it is designed for storing a date/time information somewhere. If you use a Calendar object, you could modify it after it is set to a persistent entity that performs some business logic with the date/time information. This is very dangerous, because the entity has no way to recognize this change. The Calendar class is designed for operations on date/time, like adding days or something like that.

Playing around with your example I get the following:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class TimeZoneExtracter {

    public static final void main(String[] args) throws ParseException {
        DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
        System.out.println(dbFormatter.getTimeZone());
        dbFormatter.parse("Fr, September 26, 2008 8:30 PM Eastern Daylight Time");
        System.out.println(dbFormatter.getTimeZone());
    }

}

Output:

sun.util.calendar.ZoneInfo[id="Europe/Berlin"... sun.util.calendar.ZoneInfo[id="Africa/Addis_Ababa"...

Is this the result you wanted?

Roland Schneider
A: 

@Ed Thomas:

I've tried something very similar to your example and I get very different results:

String testString = "Friday, September 26, 2008 8:30 PM Pacific Standard Time";
DateFormat df = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");

System.out.println("The default TimeZone is: " + TimeZone.getDefault().getDisplayName());

System.out.println("DateFormat timezone before parse: " + df.getTimeZone().getDisplayName());

Date date = df.parse(testString);

System.out.println("Parsed [" + testString + "] to Date: " + date);

System.out.println("DateFormat timezone after parse: " + df.getTimeZone().getDisplayName());

Output:

The default TimeZone is: Eastern Standard Time

DateFormat timezone before parse: Eastern Standard Time

Parsed [Friday, September 26, 2008 8:30 PM Pacific Standard Time] to Date: Sat Sep 27 00:30:00 EDT 2008

DateFormat timezone after parse: Eastern Standard Time

Seems like DateFormat.getTimeZone() returns the same TimeZone before and after the parse()... even if I throw in an explicit setTimeZone() before calling parse().

Looking at the source for DateFormat and SimpleDateFormat, seems like getTimeZone() just returns the TimeZone of the underlying Calendar... which will default to the Calendar of the default Locale/TimeZone unless you specify a certain one to use.

matt b
What JVM are you using?
Ed Thomas
java version "1.4.2_14"Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_14-b05)Java HotSpot(TM) Client VM (build 1.4.2_14-b05, mixed mode)
matt b
A: 

Ed has it right. you want the timeZone on the DateFormat object after the time has been parsed.

 String rawDate = "Friday, September 26, 2008 8:30 PM Eastern Daylight Time";
 DateFormat dbFormatter = new SimpleDateFormat("EEEE, MMMM dd, yyyy hh:mm aa zzzz");
 Date scheduledDate = dbFormatter.parse(rawDate);

 System.out.println(rawDate); 
 System.out.println(scheduledDate); 
 System.out.println(dbFormatter.getTimeZone().getDisplayName());

produces

Friday, September 26, 2008 8:30 PM Eastern Daylight Time
Fri Sep 26 20:30:00 CDT 2008
Eastern Standard Time
Mike Pone
You might want to test with something other than "Eastern Daylight Time" in the date String - dbFormatter.getTimeZone() is just returning the default (your) timezone.
matt b
+2  A: 

I recommend checking out the Joda Time date and time API. I have recently been converted to a believer in it as it tends to be highly superior to the built-in support for dates and times in Java. In particular, you should check out the DateTimeZone class. Hope this helps.

http://joda-time.sourceforge.net/

http://joda-time.sourceforge.net/api-release/index.html

Kamikaze Mercenary