tl;dr
A Date
(and Instant
) are always in UTC by definition. So no need to futz with time zone.
Instant.now() // Capture current moment in UTC.
Or, if you must use the troublesome legacy class Date
:
java.util.Date.from( Instant.now() ) // Avoid the legacy classes whenever possible. When required, you can convert back-and-forth via new methods added to the old classes as seen here.
Always specify time zone
Never rely on the current default time zone of either your host OS or your JVM. That default value is out of your control and can change at any moment during runtime.
Instead:
- Always use the java.time classes rather than the troublesome old legacy classes seen in your code.
- Always specify your desired/expected time zone as an optional argument to the various java.time methods rather than rely implicitly on the JVM’s current default.
java.time
You appear to be trying to get the current moment as a java.util.Date
object. That legacy class represents a value in UTC, so the time zone is irrelevant.
Instant
The modern replacement for that class is java.time.Instant
. The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Capturing the current moment is simple: Instant.now
.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
If you must have Date
to inter-operate with old code not yet updated to java.time, convert by calling new methods added to the old classes.
java.util.Date javaUtilDate = java.util.Date.from( instant ) ;
Either way, be very aware that both a Date
and an Instant
represent a point on the timeline in UTC, always UTC.
UTC versus London Time
Also, be aware that UTC is not London time, a common misconception given that UTC/GMT is tracked from a point at the Royal Observatory, Greenwich. Actually, London has a history of anomalies in its offset-from-UTC, including the adoption of Daylight Saving Time (DST).
To get London time, assign a ZoneId
to get a ZonedDateTime
.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Europe/London" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, same point on the timeline, but viewed with a different wall-clock time used by the people of a particular region (time zone).
Generally, best practice is to keep your servers in UTC, and to do as much of your business logic, storage, and exchange of date-time values in UTC. Use a zoned value such as London time only when required either by business logic or presentation to user.
Notice in the code seen above that the current default time zone of any computer or JVM is irrelevant. A change in that default has no effect on your code.
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
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.