tl;dr
ChronoUnit
.WEEKS
.between(
myJavaUtilDate_Start.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) ,
myJavaUtilDate_Stop.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) )
)
7
java.time
The java.time framework is built into Java 8 and later. These new classes supplant the old date-time classes bundled with the earliest versions of Java.
The java.time classes also supplant the highly successful Joda-Time framework. Both java.time and Joda-Time are led by Stephen Colbourne.
Instant
replaces java.util.Date
The modern class Instant
replaces the legacy class java.util.Date
. Both represent a moment in UTC, a specific point on the timeline. Both internally use a count since the same epoch reference of the first moment of 1970 in UTC, 1970-01-01T00:00Z. The old class uses a count of milliseconds, while Instant
uses a finer count of nanoseconds.
To convert, call new methods added to the old classes.
Instant start = myJavaUtilDateStart.toInstant() ;
Instant stop = myJavaUtilDateStop.toInstant() ;
Let's make this concrete with some example values.
Instant start = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).toInstant();
Instant stop = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).plusWeeks(7 ).toInstant();
Moments versus dates
Both of our Instant
objects represent a moment. The goal is a count of weeks. Weeks means days, and days mean certain dates on the calendar.
So we have a bit of a mismatch. For any given moment, the date varies around the globe by time zone. A few minutes after midnight in Paris France is a new date. Meanwhile in Montréal Québec, being several hours behind, that same moment is still “yesterday”, the date before on the calendar. So we cannot directly calculate weeks from a pair of moments.
You must first decide on the time zone by which you want to perceive a calendar for those moments.
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/Montreal" ) ;
ZonedDateTime
Apply this ZoneId
to our Instant
objects to adjust into a time zone, yielding a pair of ZonedDateTime
objects.
ZonedDateTime startZdt = start.atZone( z ) ;
ZonedDateTime stopZdt = stop.atZone( z ) ;
ChronoUnit.WEEKS
Now we can use the ChronoUnit
enum to calculate elapsed weeks.
long weeks = ChronoUnit.WEEKS.between( startZdt , stopZdt );
Dump to console.
System.out.println( "start.toString() = " + start );
System.out.println( "stop.toString() = " + stop );
System.out.println( "startZdt.toString() = " + startZdt );
System.out.println( "stopZdt.toString() = " + stopZdt );
System.out.println( "weeksCount: " + weeksCount );
See this code run live at IdeOne.com.
start.toString() = 2020-01-23T15:30:00Z
stop.toString() = 2020-03-12T15:30:00Z
startZdt.toString() = 2020-01-23T10:30-05:00[America/Montreal]
stopZdt.toString() = 2020-03-12T11:30-04:00[America/Montreal]
weeksCount: 7
ThreeTen-Extra
The ThreeTen-Extra project adds functionality to the java.time framework built into Java 8 and later.
Weeks
class
That project includes a Weeks
class to represent a number of weeks. Not only can it calculate, it is also meant to be used in your code as a type-safe object. Such use also helps to make your code self-documenting.
You can instantiate by providing a pair of points in time with the Weeks.between
method. Those points in time can be anything implementing java.time.temporal.Temporal including Instant
, LocalDate
, OffsetDateTime
, ZonedDateTime
, Year
, YearMonth
, and more.
Your java.util.Date
objects can be easily converted to Instant
objects, moments on the timeline in UTC with a resolution in nanoseconds. Look at new methods added to the old date-time classes. For going from Date to Instant, call java.util.Date::toInstant
.
Weeks weeks = Weeks.between( startZdt , stopZdt );
You can ask for the number of weeks.
int weeksNumber = weeks.getAmount(); // The number of weeks in this Weeks object.
You can also do much more.
Generate a string in standard ISO 8601 format. The P
marks the beginning. The W
indicates a number of weeks.
PW7
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.