capturing timezone when parsing java.util.Date

R

Robert Dodier

Hello,

When a string like "2009-06-26 14:13:00-0400" is parsed to
a java.util.Date via java.text.SimpleDateFormat, the timezone
in the string is lost --- the timezone of the result isn't UTC-04:00,
instead it's the default timezone (or date formatter's timezone,
if it was assigned a non-default value).

I could pull off the trailing timezone from the string and parse
it separately and adjust the timezone of the date by hand,
but I can't see a way to do that. java.util.Date doesn't have a
method to change the timezone. java.util.Calendar has
setTimeZone, but the following:

java.util.Date d0 = <whatever>;
java.util.Calendar c = java.util.Calendar.getInstance ();
c.setTime (d0);
c.setTimeZone (<whatever>);
d1 = c.getTime ();

yields a date which has the default timezone.
I can't see another way to do it with Calendar.

Any advice about how to capture the timezone when parsing
a date would be appreciated. Also, if someone wants to
recommend a different time/date library, I would be interested.
Java's built-in time/date functions are a colossal disaster,
but I digress.

best

Robert Dodier
 
L

Lew

Robert said:

Once was enough to post your query.
When a string like "2009-06-26 14:13:00-0400" is parsed to
a java.util.Date via java.text.SimpleDateFormat, the timezone
in the string is lost --- the timezone of the result isn't UTC-04:00,
instead it's the default timezone (or date formatter's timezone,
if it was assigned a non-default value).

I could pull off the trailing timezone from the string and parse
it separately and adjust the timezone of the date by hand,
but I can't see a way to do that. java.util.Date doesn't have a
method to change the timezone. java.util.Calendar has
setTimeZone, but the following:

java.util.Date d0 = <whatever>;

Don't forget the 'import' feature.
java.util.Calendar c = java.util.Calendar.getInstance ();
c.setTime (d0);
c.setTimeZone (<whatever>);
d1 = c.getTime ();

yields a date which has the default timezone.
I can't see another way to do it with Calendar.

Any advice about how to capture the timezone when parsing
a date would be appreciated. Also, if someone wants to
recommend a different time/date library, I would be interested.
Java's built-in time/date functions are a colossal disaster,
but I digress.

Date objects don't contain timezone information.

From said:
the Date class is intended to reflect coordinated universal time (UTC)

Use a combination of java.util.Calendar and java.text.DateFormat.
 
J

John B. Matthews

Robert Dodier said:
When a string like "2009-06-26 14:13:00-0400" is parsed to a
java.util.Date via java.text.SimpleDateFormat, the timezone in the
string is lost --- the timezone of the result isn't UTC-04:00,
instead it's the default timezone (or date formatter's timezone, if
it was assigned a non-default value).

When the string "2009-06-26 14:13:00-0400" is parsed, the resulting Date
doesn't have a Timezone; it is merely the number of milliseconds since
the epoch, UT. It can be formatted to show the same Date seen on a clock
in any Timezone:

<console>
2009-06-26 14:13:00GMT-04:00 GMT-04:00 1246039980000
2009-06-26 14:13:00EDT US/Eastern 1246039980000
2009-06-26 19:13:00BST Europe/London 1246039980000
2009-06-26 20:13:00CEST Europe/Berlin 1246039980000
</console>

<code>
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class TestSDF {

private static final String s = "yyyy-MM-dd HH:mm:sszz";
private static final DateFormat f = new SimpleDateFormat(s);

public static void main(String[] args) {
try {
String str = "2009-06-26 14:13:00-0400";
Date date = f.parse(str);
print("GMT-04:00", date);
print("US/Eastern", date);
print("Europe/London", date);
print("Europe/Berlin", date);
} catch (ParseException e) {
e.printStackTrace(System.err);
}
}
private static void print(String tz, Date d) {
f.setTimeZone(TimeZone.getTimeZone(tz));
System.out.println(f.format(d)
+ " " + tz
+ " " + d.getTime());
}
}
</code>

[...]
Any advice about how to capture the timezone when parsing
a date would be appreciated.

"You can use the getAvailableIDs method to iterate through all the
supported time zone IDs," or use a CustomID, described here:

<http://java.sun.com/javase/6/docs/api/java/util/TimeZone.html>
 
D

Dr J R Stockton

In comp.lang.java.programmer message <[email protected]>,
When a string like "2009-06-26 14:13:00-0400" is parsed to
a java.util.Date via java.text.SimpleDateFormat, the timezone
in the string is lost --- the timezone of the result isn't UTC-04:00,

That which is in the string is not a Time Zone, it is a Time Offset.

Time Zones govern, or are governed by, Winter Time.
 
R

Roedy Green

Time Zones govern, or are governed by, Winter Time.

except in the Southern hemisphere.
--
Roedy Green Canadian Mind Products
http://mindprod.com

"Deer hunting would be fine sport, if only the deer had guns."
~ William S. Gilbert of Gilbert and Sullivan
 
D

Dr J R Stockton

In comp.lang.java.programmer message <frid455v3ard1na2933517ml5th8mer2bp
@4ax.com>, Sat, 27 Jun 2009 18:46:37, Roedy Green <see_website@mindprod.
com.invalid> posted:
except in the Southern hemisphere.


No. Remember that they have winter in the middle of the Gregorian
calendar year.

Chile and Labrador are both in the zone four hours behind Greenwich,
But currently Labrador clocks are two hours ahead of Chilean ones, and
at Christmas Chilean ones will be two hours ahead of Labrador ones.

Few Time Zones contain populous parts that advance the clocks in the
first half of the calendar year and other populous parts that advance
the clocks in the second half of the calendar year, AFAICS; although
there's a fair area north of AU/NZ that advances its clocks in Summer.
 
R

Robert Dodier

Once was enough to post your query.

Gosh, Lew, I'll be more careful next time.
Don't forget the 'import' feature.

Aha! So *that* is why is doesn't work.
Wait a minute, "<whatever>" isn't valid syntax.
I think something has escaped your eagle eye!

Keep up the good work!

Robert Dodier
 
R

Robert Dodier

That which is in the string is not a Time Zone, it is a Time Offset.

OK. Is there a way to capture it? I could do it by hand,
but I'd like to get Java to do it for me.

Thanks for your help,

Robert Dodier
 
R

Robert Dodier

When the string "2009-06-26 14:13:00-0400" is parsed,
the resulting Date doesn't have a Timezone; it is merely
the number of milliseconds since the epoch, UT.

Understood. Is there a Java function which records both
the milliseconds since the epoch and the timezone or offset?
"You can use the getAvailableIDs method to iterate through all the
supported time zone IDs," or use a CustomID, described here:

Yes, but that doesn't extract the timezone ID from an input string.

Thanks for your help,

Robert Dodier
 
L

Lew

Robert said:
Understood. Is there a Java function which records both
the milliseconds since the epoch and the timezone or offset?

As mentioned upthread, java.util.Calendar has that.
Yes, but that doesn't extract the timezone ID from an input string.

As mentioned upthread, java.text.DateFormat, in particular
SimpleDateFormat, has that.
 
J

John B. Matthews

Lew said:
As mentioned upthread, java.util.Calendar has that.


As mentioned upthread, java.text.DateFormat, in particular
SimpleDateFormat, has that.

Robert: Lew is correct. Your example above specifies an RFC 822 4-digit
time zone: -0400. When SimpleDateFormat parses your example string, it
uses that to set the Date. As Dr, Stockton points out, that four-digit
quantity is a time offset, not a TimeZone. More than one TimeZone may
have the given offset: Toronto, NewYork, Havana or elsewhere along the
same general meridian:

<http://mindprod.com/applet/tz.html>

I think you'll need more information to convert a an RFC 822 4-digit
offset into a Java TimeZone.
 
L

Lothar Kimmeringer

Robert said:
When a string like "2009-06-26 14:13:00-0400" is parsed to
a java.util.Date via java.text.SimpleDateFormat, the timezone
in the string is lost --- the timezone of the result isn't UTC-04:00,
instead it's the default timezone (or date formatter's timezone,
if it was assigned a non-default value).

I wouldn't call it lost. It's taken into account to calculate the
time for the desired timezone (the local one if not specified
explicitly). In general this is what you need when you're
parsing date-strings to Date-instances.
java.util.Date d0 = <whatever>;
java.util.Calendar c = java.util.Calendar.getInstance ();
c.setTime (d0);
c.setTimeZone (<whatever>);
d1 = c.getTime ();

yields a date which has the default timezone.
I can't see another way to do it with Calendar.

Date doesn't contain timezone-informations, so a
calendar.getTime always returns the milliseconds since
January 1st, 1970 UTC. This is the way Date works (and is
documented).
Any advice about how to capture the timezone when parsing
a date would be appreciated. Also, if someone wants to
recommend a different time/date library, I would be interested.
Java's built-in time/date functions are a colossal disaster,
but I digress.

For what exactly do you need the offset-information (not the time-
zone as already been pointed out by others)? If you want to use it
for reformatting the date, you might just look for a way to get
the Locale of the one to format the time for (e.g. by the request-
headers a browser sends or evaluating the location the IP or
<whatever>.


Regards, Lothar
--
Lothar Kimmeringer E-Mail: (e-mail address removed)
PGP-encrypted mails preferred (Key-ID: 0x8BC3CD81)

Always remember: The answer is forty-two, there can only be wrong
questions!
 
R

Robert Dodier

I wouldn't call it lost.

It is indeed lost in the sense that two date strings which
have different timezone offsets can be parsed to the
same milliseconds-since-the-epoch, so given only the
parse output there is no way to determine from which
timezone it originated.
For what exactly do you need the offset-information (not the time-
zone as already been pointed out by others)? If you want to use it
for reformatting the date, you might just look for a way to get
the Locale of the one to format the time for (e.g. by the request-
headers a browser sends or evaluating the location the IP or
<whatever>.

Yes. I have concluded that I'll have to parse the timezone
offset by hand and store it separately.

Robert Dodier
 
J

John B. Matthews

Robert Dodier said:
It is indeed lost in the sense that two date strings which
have different timezone offsets can be parsed to the
same milliseconds-since-the-epoch, so given only the
parse output there is no way to determine from which
timezone it originated.


Yes. I have concluded that I'll have to parse the timezone
offset by hand and store it separately.

I'm curious what you'll do with the information.
 
L

Lew

Robert said:
Yes. I have concluded that I'll have to parse the timezone
offset by hand and store it separately.

Or you could use java.text.DateFormat to parse the timezone information
<http://java.sun.com/javase/6/docs/api/java/text/DateFormat.html#parse(java.lang.String)>
using the parsing pattern "Z" at the end of the pattern string in a
java.text.SimpleDateFormat
<http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html>
and store the whole thing in a java.util.Calendar
<http://java.sun.com/javase/6/docs/api/java/util/Calendar.html>
which can maintain time zone (or rather, offset) information quite handily.
<http://java.sun.com/javase/6/docs/api/java/util/Calendar.html#getTimeZone()>
<http://java.sun.com/javase/6/docs/api/java/util/Calendar.html#setTimeZone(java.util.TimeZone)>
as, for that matter, can DateFormat
<http://java.sun.com/javase/6/docs/api/java/text/DateFormat.html#getTimeZone()>
<http://java.sun.com/javase/6/docs/api/java/text/DateFormat.html#setTimeZone(java.util.TimeZone)>
..
 
A

Arne Vajhøj

Robert said:
When a string like "2009-06-26 14:13:00-0400" is parsed to
a java.util.Date via java.text.SimpleDateFormat, the timezone
in the string is lost --- the timezone of the result isn't UTC-04:00,
instead it's the default timezone (or date formatter's timezone,
if it was assigned a non-default value).

The result is a timezone independent real time.
I could pull off the trailing timezone from the string and parse
it separately and adjust the timezone of the date by hand,
but I can't see a way to do that.

You decide timezone when you output the time.
Any advice about how to capture the timezone when parsing
a date would be appreciated.

Try and look at the following:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class DateParseFormat {
private static DateFormat dfoffset;
private static DateFormat dfminus4;
private static DateFormat dfplus2;
private static void test(String s) throws ParseException {
System.out.println("Time string: " + s);
Date d = dfoffset.parse(s);
System.out.println("Binary time when parsed: " + d.getTime());
System.out.println("Formatted in -4: " + dfminus4.format(d));
System.out.println("Formatted in +2: " + dfplus2.format(d));
}
public static void main(String[] args) throws ParseException {
dfoffset = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");
dfminus4 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dfminus4.setTimeZone(TimeZone.getTimeZone("GMT-04:00"));
dfplus2= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dfplus2.setTimeZone(TimeZone.getTimeZone("GMT+02:00"));
test("2009-06-26 14:13:00-0400");
test("2009-06-26 14:13:00+0200");
}
}

It outputs:

Time string: 2009-06-26 14:13:00-0400
Binary time when parsed: 1246039980000
Formatted in -4: 2009-06-26 14:13:00
Formatted in +2: 2009-06-26 20:13:00
Time string: 2009-06-26 14:13:00+0200
Binary time when parsed: 1246018380000
Formatted in -4: 2009-06-26 08:13:00
Formatted in +2: 2009-06-26 14:13:00

Note that:
* parse does use the time zone information
* Date is basically a binary real time independent of timezones
* you decide timezone when formatting for output
Also, if someone wants to
recommend a different time/date library, I would be interested.
Java's built-in time/date functions are a colossal disaster,
but I digress.

It is currently in second edition. Third edition is said to be
on its way. Someone agrees with you.

But I don't think you example is among the problems.

Arne
 
M

Mayeul

Lew said:
Or you could use java.text.DateFormat to parse the timezone information
<http://java.sun.com/javase/6/docs/api/java/text/DateFormat.html#parse(java.lang.String)>

using the parsing pattern "Z" at the end of the pattern string in a
java.text.SimpleDateFormat
<http://java.sun.com/javase/6/docs/api/java/text/SimpleDateFormat.html>


Maybe it's just me, but I still can't figure out how can
DateFormat.parse() give any sort of information about the time zone or
offset of the date it just parsed.

Which kinda surprises me, actually. Never had any need for that, never
suspected I could not do that if I wanted to.
 
L

Lew

Mayeul said:
Maybe it's just me, but I still can't figure out how can
DateFormat.parse() give any sort of information about the time zone or
offset of the date it just parsed.

That's because the offset of the 'Date' that results from
'DateFormat#parse()' is always 0. No further information is
necessary. You already know that 'Date' stores time in a time zone-
independent fashion.
Which kinda surprises me, actually. Never had any need for that, never
suspected I could not do that if I wanted to.

You don't need it. As several in this thread keep saying,
'java.util.Date' represents time in milliseconds since epoch GHT.
Time zone or offset information is a display characteristic only. You
parse the offset with 'DateFormat#parse()' (strangely enough), and
format it for display with 'DateFormat#format()' (strangely enough).

Nothing surprising there at all. It's all in the Javadocs for the
relevant classes and methods.

Let's summarize this information again:

'java.util.Date' records time in GMT. There is no time zone
information in it. There is time zone information in
'java.util.Calendar' and in 'java.text.DateFormat' and
'java.text.SimpleDateFormat'. You use the time zone-aware classes to
parse and format (using, say, 'parse()' and 'format()') 'String'
instances to 'Date' and vice versa. It's all in there if you need it,
just not in 'Date' by itself, which records time in GMT. This poses
no trouble, because the other classes can handle your time zone (or
offset) needs just fine.

Read the Javadocs.
 
M

Mayeul

Lew said:
That's because the offset of the 'Date' that results from
'DateFormat#parse()' is always 0. No further information is
necessary. You already know that 'Date' stores time in a time zone-
independent fashion.


You don't need it.

Who knows? Indeed I fail to imagine a real-life use case where I would
actually need it. It tends to make me believe I actually don't need it.

But, let's imagine anyway I do want to format the obtained Date with the
same offset I obtained it from. In that case, I would need it.
 
L

Lew

Even after reading the Javadocs, as well as this discussion, I still
don't know how to deal with the following use-case: Record a date in a
format that allows for time comparisons and adjustments, but display it
appropriately for the original time zone.

It's easy if I want to display all dates in the current locale, or in
some specified locale. I just parse to get a Date, do my comparisons
etc. on that Date object, and then format to the required locale.

It is not so easy, as far as I can tell, if I want to display each date
in its original time zone.

Presumably, I need to store both a Date and a TimeZone, but how do I get
the TimeZone from parsing the original String?

Well, obviously you'd have to do more work in that use case, but you
can still use the same classes with the addition of
'java.util.TimeZone', in particular
<http://java.sun.com/javase/6/docs/api/java/util/
TimeZone.html#getTimeZone(java.lang.String)>
..

The use of 'TimeZone' is hinted by the Javadocs for 'Calendar' and
'DateFormat'.

The process would go something like extract the part of the 'String'
that represents the time offset. Form a 'TimeZone' from it and store
it in the 'Calendar' along with the parsed 'Date' information. Bob's
your uncle.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,740
Latest member
AdolphBig6

Latest Threads

Top