*
The moose likes Beginning Java and the fly likes timezone woes Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "timezone woes" Watch "timezone woes" New topic
Author

timezone woes

kato Kwong
Greenhorn

Joined: Sep 23, 2011
Posts: 27
Hello,

I am having trouble understanding how Calendar, Date and TimeZone cooperate. Here is my code:



And here is the output:



So my local timezone is different to "Asia/Calcutta". But why is my local time zone involved in this test? I could understand if it was a feature of printing getTime() using System.out, but the assertion should still succeed right?

Any help appreciated...

Kato
Tim Moores
Rancher

Joined: Sep 21, 2011
Posts: 2408
Calendar.getTime returns a Date object - which has no concept of timezones other than what its javadocs state about UTC and GMT. So my guess would be that you're 4 hours ahead of UTC/GMT.
kato Kwong
Greenhorn

Joined: Sep 23, 2011
Posts: 27
Thanks for the response Tim.

I don't understand why Date needs to have any concept of TimeZone for this test to succeed.

Why does my Calendar instance, created against a given time zone (Asia/Calcutta), not return a Date instance which represents the time of the Calendar in the timezone?

Still baffled...:-(

Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14350
    
  22


Class Date represents an "absolute" moment in time (independent of the time zone).

To express a moment in time with year, day, month, hours, minutes, seconds and milliseconds fields, you need to interpret the moment relative to a time zone. For example, the current moment is 2012-03-27 13:04:00.000 in my time zone (which is CEST, Central European Summer Time). In another time zone, the hours (and possibly other fields) would be different, even though it indicates the exact same moment in time.

Class Date doesn't know anything about time zones by itself. If you print a Date object, by implicitly calling toString() on it:

then it will be interpreted and printed in the time zone of your system. For example, for me it would print the date and time in CEST.

Class Calendar does know about time zones. If you get a Calendar object with a specific time zone setting, for example "Asia/Calcutta", and you ask it to return the hours field, it will give you the hours in the time zone that you've set on the Calendar object - not your system time zone.

When you call getTime() on class Calendar, you get a Date object that represents the moment in time that the Calendar is set to. But since class Date doesn't know anything about time zones, the Date object doesn't know what time zone the Calendar object was set to.

If you want to show the Date format in a specific time zone, then format it to a string by using a SimpleDateFormat, and set the desired time zone on the SimpleDateFormat object:

Note that the API documentation of java.util.Date.getHours() says:
API documentation wrote:
Returns the hour represented by this Date object. The returned value is a number (0 through 23) representing the hour within the day that contains or begins with the instant in time represented by this Date object, as interpreted in the local time zone.

(By the way, that method is deprecated, which means you shouldn't use it).

Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 8 API documentation
kato Kwong
Greenhorn

Joined: Sep 23, 2011
Posts: 27
Thanks Jesper, that's a lot of information!

When you call getTime() on class Calendar, you get a Date object that represents the moment in time that the Calendar is set to. But since class Date doesn't know anything about time zones, the Date object doesn't know what time zone the Calendar object was set to.



OK. So my Date object should be set to the correct time according to the timezone of the Calendar? Or is it set to a GMT value that represents the time in the timezone?


My example is contrived because I am writing a JUnit test to ensure that a Date object is created from a Calendar for a given timezone. So far, I cannot prove it, because every time I print or compare something, it seems to be converted.

Ultimately, I want to pass the Date around, use it in comparisons and write it to a data source.


Tim Moores
Rancher

Joined: Sep 21, 2011
Posts: 2408
Why not refactor to use Calendar instead of Date?
kato Kwong
Greenhorn

Joined: Sep 23, 2011
Posts: 27
Yes, so a Date is created with the value of the Calendar in GMT:



Thus it will make no difference whether I use Calendar or Date as long as I know what the values are relative to, i.e. GMT. Besides, I don't really like passing around Calendars for dates.

Thanks all.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14350
    
  22

kato Kwong wrote:Yes, so a Date is created with the value of the Calendar in GMT:

No. When you call getTime() on a Calendar object, you get a Date object that represents the moment in time that the Calendar is set to. That moment, by itself, is independent of the time zone. If you want to express the moment as a set of year, month, day, hours, minutes, seconds, milliseconds fields, then you need to interpret the moment relative to a time zone.

Your second test doesn't show that the Date is created with the value of the Calendar in GMT.

The two calendars that you create in the test are set to the same moment in time (the current time), but with different time zone settings. In the assert, you get the Date object from both calendars, and since both calendars refer to the same instant in time, they will be equal. "Now" in the UK is always "now" in Calcutta. Doesn't matter that the clock in the UK is now at 13:41 and in Calcutta at 18:41 - now is now!

Note that it doesn't matter which two time zones you use, you could replace "Zulu" and "Asia/Calcutta" by two arbitrary other time zones and the assert will still pass. "Now" in some arbitrary place on the globe is the same "now" as on any other place on the globe - no matter what the time zones are in those two places.
kato Kwong
Greenhorn

Joined: Sep 23, 2011
Posts: 27
To be sure...

From Date API documentation:

The class Date represents a specific instant in time, with millisecond precision...
The Date class is intended to reflect coordinated universal time (UTC)...
Some computer standards are defined in terms of Greenwich mean time (GMT), which is equivalent to universal time (UT). GMT is the "civil" name for the standard; UT is the "scientific" name for the same standard. The distinction between UTC and UT is that UTC is based on an atomic clock and UT is based on astronomical observations...


So Date is not strictly independent of time zone.

But I agree with your points: my test does not show the dates are created in GMT. It does show that which ever time zone is specified, the same Date is created and that is what I didn't appreciate before. As you say
you could replace "Zulu" and "Asia/Calcutta" by two arbitrary other time zones and the assert will still pass


As long as I create my dates from Calendars configured with the correct time zones, then my local times will be converted to the same relative Dates.

Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14350
    
  22

Date is not strictly independent of time zone, but that's just because we don't have any other way to indicate dates and times than with year, month, day, hours, minutes etc. fields. But when you express a specific moment with those fields, you can only do that if you also specify the time zone.

The only information that class Date contains is a number, which is the number of milliseconds that have passed since a fixed moment in time. The fixed moment in time was chosen to be 01-01-1970, 12:00:00 AM UTC. Since that fixed moment is expressed in UTC, you could indeed say that a Date is always in UTC. But strictly speaking that's not really true; the Date object itself doesn't contain information about a time zone, it's just the reference moment that's expressed in UTC.

Anyway, the important thing to know is that the Date object doesn't know what time zone the Calendar object that it came from was set to. In other words, if you have a Date object that came from a Calendar, it's not possible to know from just that Date object alone to which time zone the Calendar was set.

I know that this is confusing for a lot of people. People sometimes ask question like "how do I get a Date object in some time zone" - well, you don't, because a Date doesn't know about time zones.

The date and calendar API of Java is unfortunately not a very well designed API. There's a popular library called Joda Time which is much better than Java's date and calendar API. If you need to work with dates and times, I'd recommend using Joda Time.
Tim Moores
Rancher

Joined: Sep 21, 2011
Posts: 2408
It also bears remembering that when the Java APi was designed there was no one in the world -including the Java API designers, some of whom were very bright computer scientists- who was skilled in designing Java APIs. Plus, I18N was not yet on everybody's mind. So not everything you see in the Java class libraries today will make sense with all the hindsight of 2012.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14350
    
  22

That's true, you can't really blame the designers of the original Java API.

There is a Java specification request, JSR-310, by Stephen Colebourne, the author of Joda Time, to design a new standard Java date and time API, which will obviously be based on Joda Time. Hopefully that will be included in Java 8. (Ofcourse that doesn't mean that java.util.Date and java.util.Calendar will disappear, but at least we'll also have a much nicer standard API for dates and times).
kato Kwong
Greenhorn

Joined: Sep 23, 2011
Posts: 27
People sometimes ask question like "how do I get a Date object in some time zone" - well, you don't, because a Date doesn't know about time zones.


Yes, in my case I didn't really understand time zones and I didn't think to understand how they should be modelled.

So even if I understood that Date was just a number and did not hold timezone information, I thought the number would be relative to the fixed point in time and include the time zone offset. Of course, although it doesn't know about TimeZone objects, this means it does actually hold time zone information. This seemed reasonable because, from the point of view of someone in a timezone, that is my time now and I don't care about time anywhere else.

But then, if I decided to care about time elsewhere, the Date object would not be as useful as the actual implementation, because I would constantly need to convert between timezones. With the actual implementation, once a Date is created, every Date can be compared directly without regard to timezone.

So at the risk of defending the java API, this aspect of the API is good. I think time zones are confusing with or without the Java API
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: timezone woes