Timezones are confusing to say the least. Here are four things to keep in mind when working with timezones in Java.
1. Timezones are relative to UTC
UTC, which stands for "Coordinated Universal Time", is always the same no matter where on the planet you are. The term "GMT" is often used as well. While GMT is pretty much identical to UTC, it's not exactly the same. UTC is scientifically defined, while GMT is not.
A timezone is an offset from UTC. For example, my timezone is currently 4 hours behind UTC. However, a timezone's offset may change depending on the time of year. For example, my timezone is 4 hours behind UTC for half the year (daylight savings time) and 5 hours behind UTC for the other half of the year (standard time). This is why it's preferable to represent timezones using their IDs (such as "America/New_York", described in more detail below) instead of their offsets (such as "-0400"). An offset can change depending on the time of year, but a timezone ID encapsulates these offset variations.
Fun fact: You might have noticed that the letters in the acronym "UTC" don't match up with "Coordinated Universal Time". "UTC" actually arose as a compromise between the English version "CUT" (Coordinated Universal Time), and the French version "TUC" (Temps Universel Coordonné).
2. Date
objects use UTC
Whenever you call the toString()
method on a java.util.Date
object (for example, by printing the object to the console), it will generate a string that looks something like this:
Thu Jun 20 13:23:52 EDT 2013
This might lead you to believe that this is the exact timestamp that the object is holding. Not necessarily. Internally, Date
objects store their timestamps in UTC. When you call toString()
, it converts the UTC timestamp to your JVM's default timezone.
3. Timezones are clothing
Think of timezones as just different sets of clothing a timestamp can wear. It can put on a sweater, a jacket, or a tuxedo, but underneath it all, it's still a UTC timestamp. To format a Date
object using a timezone of your choosing, call the setTimeZone()
method on the DateFormat
class.
DateFormat formatter = new SimpleDateFormat("HH:mm Z"); TimeZone timezone = TimeZone.getTimeZone("Europe/Madrid"); formatter.setTimeZone(timezone); System.out.println(formatter.format(new Date())); //prints: 19:50 +0200
In the example above, I'm printing the current time in Madrid, Spain (and surrounding areas). The "+0200" part describes the timezone's offset from UTC at that moment in time. It shows that the timezone is 2 hours and 0 minutes ahead of UTC. To give another example of an offset, "-0430" would mean that the timezone is 4 hours and 30 minutes behind UTC.
You might be wondering where a list of these timezone identifier strings can be found. A source that I like to use is from the PHP user manual. But the official listing can be found in what's known as the TZ database.
4. The TimeZone
class is quirky
Note that if an unrecognized timezone ID is passed into the TimeZone.getTimeZone()
method, the method will return an object representing the "GMT" timezone. It would be less confusing if it just returned null, but who am I to complain.
TimeZone timezone = TimeZone.getTimeZone("Bogus/Timezone"); if ("GMT".equals(timezone.getID())){ //timezone not found! } else { //timezone found }
3 comments:
"Think of timezones as just different sets of clothing a timestamp can wear. It can put on a sweater, a jacket, or a tuxedo" ... I like to think of my timezones as wearing a twead sweaters and double pleated trousers :) But seriously, thanks for making something so convoluted seem so simple.
np
Thanks for this breakdown.
Was helpful in getting into working with java time.
Post a Comment