I have a Europe/Moscow timezone in my Mageia 4.
The code like this
System.out.println(new java.util.Date());
System.out.println(System.getProperty("user.timezone"));
returns
Fri Oct 24 13:43:22 GMT+03:00 2014
GMT+03:00
if I set the system date in 24.10.2014
and that code returns
Sun Oct 26 14:44:26 GMT+03:00 2014
GMT+03:00
if I set the system date in 26.10.2014
In my point of view it is wrong behavior of java zoneinfo system. I downloaded the tzupdater and run it, the file Europe/Moscow was updated and now its size is 705 kB.
I try the code below:
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Moscow"));
System.out.println(new java.util.Date());
System.out.println(java.util.TimeZone.getDefault());
and it returns
Fri Oct 24 15:10:34 MSK 2014
sun.util.calendar.ZoneInfo[id="Europe/Moscow",offset=10800000,dstSavings=0,useDaylight=false,transitions=79,lastRule=null]
and
Sun Oct 26 15:32:03 MSK 2014
sun.util.calendar.ZoneInfo[id="Europe/Moscow",offset=10800000,dstSavings=0,useDaylight=false,transitions=79,lastRule=null]
Why so? Why the offset is the same in these two cases?
The problem was solved by adding the definition of correct timezone.
Your second test (26.10.2014) is after the change to wintertime so you probably need to correct the time as well by -1 hour
tl;dr
+03:00
) when you mean a time zone (Europe/Moscow
)java.util.Date
.For a moment in UTC, use
java.time.Instant
.For a moment in a time zone, use
java.time.ZonedDateTime
.Offset versus time zone
As the comment by Jon Skeet notes, your JVM’s initial default time zone was not a time zone, it was merely an offset-from-UTC.
What is the difference? An offset is simply a number of hours, minutes, and seconds, positive (ahead of UTC) or negative (behind UTC). A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region. The offset for a region can change whenever the politicians so deem. For example, many politicians buy into the lunacy of Daylight Saving Time (DST), and change the offset twice a year.
So if you set your time zone to a mere offset such as
+03:00
(three hours ahead of UTC/GMT) rather than a time zone such asEurope/Moscow
, your current date-time will always be reported as three hours ahead of UTC. Changes in offset for your region such as DST will be ignored, because you said so, you said "Always three hours ahead of UTC".java.time
You are using terrible date-time classes that were supplanted years ago by the java.time classes defined in JSR 310.
Instead of
TimeZone
, useZoneId
.Avoid setting default time zone
You should only set the default time zone of your JVM as a last-ditch act of desperation.
Setting the default time zone (and default locale, by the way) immediately affects all code in all threads of all apps running within that JVM. You will be rudely changing the zone behind the backs of other programmers. You might even find that their code changes the zone behind your back, during runtime.
Better to write all your date-time handling to never rely on the current default zone (or locale). Specify explicitly your desired/expected time zone by passing optional arguments. Personally, I wish those time zone arguments were required rather than optional, to help educated programmers about date-time issue.
We can see an example of this in the code above. Notice how we pass a
ZoneId
for Russia to thenow
method. Otherwise, we would be capturing the current moment in the wall-clock time of whatever region happens to be the JVM’s current default time zone.Tip: If critical, always confirm the time zone with the user.
java.util.Date::toString
liesBe aware that the
toString
method on theDate
objects you were calling has the anti-feature of dynamically applying the JVM’s current default time zone while generating the text to represent that moment. While well-intentioned, this unfortunate design decision has confused countless programmers trying to wrangle date-time values in Java. Ajava.util.Date
is actually in UTC, as a count of milliseconds since the first moment of 1970 in UTC. The time zone shown in the string is not actually in theDate
object.But this is moot, as this is one of many reasons to avoid this class entirely. Use
java.util.Instant
instead. Instead ofGregorianCalendar
, useZonedDateTime
.About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
,Calendar
, &SimpleDateFormat
.To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for
java.sql.*
classes.Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as
Interval
,YearWeek
,YearQuarter
, and more.