Java time different from OS time

Viewed 1642

When I print date in Unix, it show the UTC time

[app@host ~]$ date
Thu Sep  6 21:16:07 UTC 2018

When I print the date from Java on the same machine

public static void main(String[] args) {
  System.out.println("date=" + new Date());
  System.out.println("date from mills=" + new Date(System.currentTimeMillis()));
  System.out.println(TimeZone.getDefault().getDisplayName());

  Instant instant = Instant.now();
  System.out.println("instant=" + instant);
  System.out.println("instant from mills=" + new Date(instant.toEpochMilli()));
}

It prints PST time

[app@host ~]$ java TimeTest
date=Thu Sep 06 14:17:09 PDT 2018
date from mills=Thu Sep 06 14:17:09 PDT 2018
Pacific Standard Time
instant=2018-09-06T21:17:09.030Z
instant from mills=Thu Sep 06 14:17:09 PDT 2018

How does Java get the PST timezone?

Also, the logback file rotation happens at UTC time and times printed in the log file show PST time.

1 Answers

tl;dr

Use only java.time classes.

Never use Date class.

Use UTC when logging.

Instant.now().toString()

2018-01-23T01:23:45.123456Z

Details

This has been addressed many times already on Stack Overflow.

The terrible old legacy date-time classes are rife with poor design choices. Among those poor choices is the Date::toString method’s behavior of dynamically applying the JVM’s current default time zone while generating the string. Well-intentioned but misleading as a java.util.Date, like a java.time.Instant, represents a moment in UTC.

On September 6 of this year, 2 PM on west coast of much of North America is simultaneously 9 PM in UTC, with an offset-from-UTC of seven hours behind UTC during Daylight Saving Time (DST). Same moment, same point on the timeline, different wall-clock time.

Why PDT?

Why PDT, Pacific Daylight Saving Time, in particular? Your JVM always has a current default time zone. Apparently your JVM is set to a current default of a zone such as America/Los_Angeles (PDT is not a real time zone).

How that default gets set depends on your JVM implementation and your settings. Usually a JVM on launch picks up on the host operating-system’s current default zone. You can pass arguments to the launch of the JVM to specify a zone rather than pick up the host OS’ default.

After launch, any code in any thread of any app within the JVM can, at any moment, change the current default time zone with a call to TimeZone.setDefault to affect immediately all other code in that JVM.

This means you should never rely on the current default zone for anything critical as its value is out of your control as a programmer. Always specify your desired/expected time zone explicitly. Even when you want to use the current default, make an explicit call to ZoneId.systemDefault.

Bonus tip: Ditto for Locale. Always a current default. But specify explicitly rather than rely implicitly on default.

Using java.time

Never use the legacy date-classes. Use only java.time classes.

When logging, always use UTC. Render text in standard ISO 8601 format as seen in Instant::toString.

Instant instant = Instant.now() ;

If you want to view that moment in the wall-clock time used by the people of a particular region, apply a time zone (ZoneId) to get a ZonedDateTime.

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

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.

Related