After some research, I have come to understand the best way manipulate timezone with Date objects is with the DateFormat object. I have created the following method to return a Date object that contains the time local to a timezone. The problem is that it is returning a time that is exactly one hour previous to the correct local time. Do I need to do something special to account for DST? I am using Java 1.5.
What time zone ID are you using? What's your local time zone?
What displays for you when you run System.out.println(new Date(System.currentTimeMillis()));?
I don't know what you are trying to do here, but this statement is not correct. A Date object simply contains a number of milliseconds since a certain point in time. You may interpret that Date as being in a certain timezone when you format it to a String, but the Date itself does not have a timezone and knows nothing of timezones. And following on from that, the signature of that method doesn't make any sense. If it returned a String, that would make sense. It would look like this:
I have created the following method to return a Date object that contains the time local to a timezone.
Right now I am passing the timezone "GMT" and "GMT+2". Both come back everytime with a Date object that contains a representation of a date that is one hour off. For instance:
When I pass "GMT", my OS clock shows 21:17, the Date object returned from the method will contain a representation of 20:17.
I don't like to keep the date in a String as it passes through my program. It is much nicer to pass and perform opertations on the Date class.
You can want that all you want, but that isn't how Date works. All you can actually have is that the Date object represents the current time. If you want to know what that time is in a particular timezone, then you have to format it as a String using code already posted in this thread.
Originally posted by Mike Broadbear:
Well, I can restate. I want whatever the Date object contains to reprepsent the current time in the timezone denoted in the single String argument.
And yes, I agree. It's better to carry Date objects around your application and only format them as Strings in the user interface. You'll have to apply the timezone choice at that point.
Additionally, using those three-letter abbreviations to look up time zones is generally a bad idea. See my last post in this thread for more info.
[Mike]: I don't like to keep the date in a String as it passes through my program. It is much nicer to pass and perform opertations on the Date class.
OK, but what you're creating is a modified schizophrenic Date that doesn't represent what it claims to represent. It's a bit like two wrongs making a right - it's currently appearing to give you the correct GMT time, but in a very confusing manner. As Paul indicated, a Date does not have any time zone info associated with it. It seems to, because the toString() method uses the default time zone, but it doesn't. It's the responsibility of the DateFormat object to render a Date as a string using a particular timezone. Paul's code does this, correctly. But if you pass it "GMT", it will give you the GMT time, not BST - same as your code.
[ June 13, 2007: Message edited by: Jim Yingst ]
So what you are saying is that a Date object is supposed to hold a representation of a given local time, and what I have done is to trick it into holding something else, and this is definitely not recommended?
We have an application that gathers information from locations around the world, and stores a timestamp in a database in whatever local time it happens to come from. What I want to do is compare these various local times to my current local time. Right now I am using the above method to get a modified timestamp (apart from the one hour off) and comparing the long return values of Date.getTime(). This is a date comparison task more than a formatting one.
Are there any cleaner methods to modify timezones and compare dates? I want to take advantage of the timzone DB with the JDK, and not have to deal with DST and such.
But you can't clean that sort of thing up using only Date, because Date doesn't know anything about timezones. You need Calendar, which does know about timezones. So here's my fix-up code:Notice that this actually does what you were trying to do with the conversion to String and back again, at least I think so. But it does work and it does take into account daylight saving time -- it's been running here since January.
I would say it's supposed to hold a representation of a given absolute time. If you and I both created a new Date() at the same instant, mine would display (using toString()) as
Wed Jun 13 17:14:59 MDT 2007
while yours might say something like (I'm just guessing)
Wed 14 Jun 2007, 00:14:59 BST
but they still mean the same time, really. Furthermore if we both serialized our Date objects and exchanged them across the net, your date would display on my machine as
Wed Jun 13 17:14:59 MDT 2007
and mine would display on your machine as
Wed 14 Jun 2007, 00:14:59 BST.
So, if you've got a properly-obtained Date, it is independent of time zone. You can compare two Dates exactly as you describe, using getTime() - or you can use the compareTo() method.
Unfortunately it's also possible that the Dates obtained from the database were somehow entered incorrectly, or the database was not configured correctly. It sounds like that's what Paul experienced, and it [i]may[i] be happening for you as well. In that case, a method like Paul's is may be appropriate to fix the data. Here, this is essentially the second wrong which makes a right, since it's not possible to remove the initial error at this point.
On the other hand, for Dates you obtain yourself (e.g. with new Date() or Calendar.getInstance().getTime()) they should already represent the absolute time correctly, and changing them with a method like Paul's would be badly confusing, I think.
So I'm not sure how clear all that was, because from here we can't really see just what's going on in your DB, or whether the dates are already entered correctly or not.
A Date object holds an absolute time; toString() simply uses the default timezone to format the date to what I probably would want to see, given my locality. So it becomes; absolute time -> printed BST
What I don't fully understand is why the initial method I posted seems to work. Let me take a stab at it:
step 1: format the current time according to a given timezone, store the result in a string.
step 2: parse this date string into a Date object, using a DateFormat with the default timezone. Since the original date string has timestamp relative to the given timezone, that time is translated into an absolute time with respect to the default timezone, which has the semi-unintended effect of shifting the time to where I want it.
step 3: (after method) when I print the date with toString(), the shifted absolute time is translated into something printable using the default timezone. (which is why I am now seeing Wed Jun 13 19:53:02 "BST" 2007 after passing "America/New_York" to the method).
Am I close?
I have been reading the Javadocs a little more closely, but they are not too in depth. Does Calendar work the same way? Some initial testing shows when I set the hour, minute, second fields and vary timezone with Calendar.setTimeZone(""), I always see the same timestamp and 'BST' when printing the date.
Yes, that sounded right.
[Mike]: Does Calendar work the same way?
In general, no, but I'm not really sure what you mean here.
[Mike]: Some initial testing shows when I set the hour, minute, second fields and vary timezone with Calendar.setTimeZone(""), I always see the same timestamp and 'BST' when printing the date.
If you use getTime() you will always get a Date, and when you print that you will always see the timezone displayed as BST. Unless you change the date to sometime in winter, and the BST will be replaced with whatever abbreviation you normally see then... could be GMT.
you should be able to change the timestamp, though, by setting various fields of the Calendar. So I'm not sure what you're doing (or not doing).