tl;dr
- Use
java.time.Clock
, ZonedDateTime
, Instant
, ZoneId
.
- Inject an altered
Clock
object as a dependency: Clock.fixed( … )
.
- Never use
Date
, Calendar
, SimpleDateFormat
, Timestamp
, TimeZone
.
Pass an altered Clock
object as a dependency
You are using terrible date-time classes that were supplanted years ago by the java.time classes defined by JSR 310.
The java.time.Clock
class offers several alternate behaviors suitable for testing. These included a fixed point in time, altered cadences, and and adjustment from the current moment.
Pass one of these Clock
objects to the various methods in the java.time classes for your testing purposes.
PST
is not a time zone. Specify a proper time zone name in the format of Continent/Region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 2-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( "America/Los_Angeles" ) ;
Build up the specific moment you have in mind for your testing.
LocalDate ld = LocalDate.of( 2019 , 2 , 11 ) ;
LocalTime lt = LocalTime.MIN ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
zdt.toString(): 2019-02-11T00:00-08:00[America/Los_Angeles]
Calling Clock.fixed
requires an Instant
, a moment in UTC. We can adjust from our zoned value to UTC by extracting an Instant
. Same moment, same point on the timeline, different wall-clock time.
Instant instant = zdt.toInstant() ;
instant.toString(): 2019-02-11T08:00:00Z
Specify a Clock
that forever reports the current moment as that specific moment, without incrementing.
Clock clock = Clock.fixed( instant , z ) ;
clock.toString(): FixedClock[2019-02-11T08:00:00Z,America/Los_Angeles]
Inject the fixed clock as a dependency.
Instant now = Instant.now( clock ) ; // Tell me a lie.
now.toString(): 2019-02-11T08:00:00Z
See this code run live at IdeOne.com.
JDBC 4.2
If you were instantiating java.sql.Timestamp
for use with a database, instead use the java.time classes. As of JDBC 4.2, we can exchange java.time objects with a database.
Your JDBC driver might have optional support for Instant
.
myPreparedStatement.setObject( … , instant ) ; // Storing data.
Instant instant = myResultSet.get( … , Instant.class ) ; // Retrieving data.
Your driver must support OffsetDateTime
.
myPreparedStatement.setObject( … , instant.atOffset( ZoneOffset.UTC ) ) ; // Storing data.
OffsetDateTime odt = myResultSet.get( … , OffsetDateTime.class ) ; // Retrieving data.
Adjust into a time zone.
ZonedDateTime zdt = odt.atZoneSameInstant( 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.