TL; dr
Is there a way, both in code and with JVM arguments, to override the current time represented through System.currentTimeMillis, besides manually changing the system clock on the host machine?
Yes.
Instant.now( Clock.fixed( Instant.parse( "2016-01-23T12:34:56Z"), ZoneOffset.UTC ) )
Clock in java.time
We have a new solution to the problem of replacing interchangeable watches to facilitate testing using fake date-time. The java.time package in Java 8 includes the abstract class java.time.Clock with an explicit purpose:
to enable the inclusion of alternative hours if necessary
You can plug in your own implementation of Clock , although you can probably find one that has already been completed to suit your needs. For your convenience, java.time includes static methods for creating custom implementations. These alternative implementations may be useful during testing.
Altered cadence
Different tick⦠methods produce watches that increase the current moment with a different cadence.
By default, Clock reports time updated as often as milliseconds in Java 8, and in Java 9 as nanoseconds (depending on your hardware). You can request that the current current moment be reported with a different granularity.
False clock
Some watches may lie, creating a result different from the result of the hardware clock of the operating system.
fixed - Reports one unchanged (non-incremental) moment as the current moment.offset - Reports the current moment, but is shifted by the Duration argument.
For example, a castle at the first moment of the earliest Christmas this year. in other words, when Santa and his reindeer make their first stop . The earliest time zone currently is Pacific/Kiritimati +14:00 to +14:00 .
LocalDate ld = LocalDate.now( ZoneId.of( "America/Montreal" ) ); LocalDate xmasThisYear = MonthDay.of( Month.DECEMBER , 25 ).atYear( ld.getYear() ); ZoneId earliestXmasZone = ZoneId.of( "Pacific/Kiritimati" ) ; ZonedDateTime zdtEarliestXmasThisYear = xmasThisYear.atStartOfDay( earliestXmasZone ); Instant instantEarliestXmasThisYear = zdtEarliestXmasThisYear.toInstant(); Clock clockEarliestXmasThisYear = Clock.fixed( instantEarliestXmasThisYear , earliestXmasZone );
Use this special fixed watch to always return the same moment. We get the first moment of Christmas day in Kiritimati , with UTC showing the wall clock fourteen hours ago, 10 a.m. on the previous date, December 24th.

Instant instant = Instant.now( clockEarliestXmasThisYear ); ZonedDateTime zdt = ZonedDateTime.now( clockEarliestXmasThisYear );
instant.toString (): 2016-12-24T10: 00: 00Z
zdt.toString (): 2016-12-25T00: 00 +14: 00 [Pacific / Kiritimati]
See the code at IdeOne.com .
True time, different time zone
You can control which time zone is assigned by the Clock implementation. This may be useful with some tests. But I do not recommend this in production code, where you should always explicitly specify the optional ZoneId or ZoneOffset .
You can specify that UTC will be the default zone.
ZonedDateTime zdtClockSystemUTC = ZonedDateTime.now ( Clock.systemUTC () );
You can specify any time zone. Specify the correct time zone name in continent/region format, such as America/Montreal , Africa/Casablanca or Pacific/Auckland . Never use an abbreviation of 3-4 letters, such as EST or IST since they are not real time zones, not standardized, and not even unique (!).
ZonedDateTime zdtClockSystem = ZonedDateTime.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
You can specify the JVM, the current default time zone should be the default for a specific Clock object.
ZonedDateTime zdtClockSystemDefaultZone = ZonedDateTime.now ( Clock.systemDefaultZone () );
Run this code for comparison. Note that they all report the same moment, the same point on the timeline. They differ only in wall clock time ; in other words, three ways to say the same thing, three ways to display the same moment.
System.out.println ( "zdtClockSystemUTC.toString(): " + zdtClockSystemUTC ); System.out.println ( "zdtClockSystem.toString(): " + zdtClockSystem ); System.out.println ( "zdtClockSystemDefaultZone.toString(): " + zdtClockSystemDefaultZone );
America/Los_Angeles was the JVM current default zone on the computer that ran this code.
zdtClockSystemUTC.toString (): 2016-12-31T20: 52: 39.688Z
zdtClockSystem.toString (): 2016-12-31T15: 52: 39.750-05: 00 [America / Montreal]
zdtClockSystemDefaultZone.toString (): 2016-12-31T12: 52: 39.762-08: 00 [America / Los_Angeles]
The Instant class is always in UTC by definition. Thus, these three associated with the Clock zone are used in exactly the same way.
Instant instantClockSystemUTC = Instant.now ( Clock.systemUTC () ); Instant instantClockSystem = Instant.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) ); Instant instantClockSystemDefaultZone = Instant.now ( Clock.systemDefaultZone () );
instantClockSystemUTC.toString (): 2016-12-31T20: 52: 39.763Z
instantClockSystem.toString (): 2016-12-31T20: 52: 39.763Z
instantClockSystemDefaultZone.toString (): 2016-12-31T20: 52: 39.763Z
Default clock
The default implementation for Instant.now is the one returned by Clock.systemUTC() . This is the implementation used when you do not specify Clock . See for yourself in the preliminary release of Java 9 source code for Instant.now .
public static Instant now() { return Clock.systemUTC().instant(); }
Clock default Clock for OffsetDateTime.now and ZonedDateTime.now is Clock.systemDefaultZone() . See Source Code .
public static ZonedDateTime now() { return now(Clock.systemDefaultZone()); }
The default implementation behavior has changed between Java 8 and Java 9. In Java 8, the current moment is fixed with a resolution of only milliseconds, despite the ability of classes to preserve nanosecond resolution. Java 9 brings a new implementation that can capture the current moment with a resolution of a nanosecond - depending, of course, on the capabilities of your computer clock.
About java.time
The java.time framework is built into Java 8 and later. These classes supersede the nasty old obsolete time classes such as java.util.Date , Calendar and SimpleDateFormat .
The Joda-Time project, now in maintenance mode , advises switching to the java.time classes.
To learn more, check out the Oracle tutorial . And search for qaru for many examples and explanations. The specification is JSR 310 .
You can exchange java.time objects directly with your database. Use a JDBC driver compatible with JDBC 4.2 or later. No strings needed, no java.sql.* Needed.
Where can I get java.time classes?
- Java SE 8 , Java SE 9 and later
- Built in.
- Part of the standard Java API with integrated implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Most of the functionality of java.time is included back in Java 6 and 7 in ThreeTen-Backport .
- Android
- Later versions of the Android package implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts the ThreeTen-Backport (mentioned above). See How to use ThreeTenABP ....
The ThreeTen-Extra project extends java.time with additional classes. This project is a proof of possible future additions to java.time. Here you can find useful classes such as Interval , YearWeek , YearQuarter and others .