I would like to have a class to represent a particular week of year - for example today it's 29 November, which is exactly week number 48 of year 2014. So, one example implementation would be:
import java.time.Year;
public class WorkingWeek {
private int weekNumber;
private Year year;
}
Another conception is to have just a week's Monday date in a WorkingWeek class, but I feel it's less intuitive and I will frequently use week-in-year number.
Is there a class in Java 8 Time API that would fit best my requirements? Or if not, what would be recommended approach?
You need to specify your definition of a week.
One option is strings. The ISO 8601 standard defines a week as beginning on a Monday, ending on Sunday, with the first week of the year being the first to contain a Thursday, resulting in 52 or 53 weeks a year.
The standard also defines a string representation for this week-of-year span of time in the format of YYYY-Www
(or omitting hypen, YYYYWww
) such as 2014-W07
. A day within the week is represented by a digit where Monday is 1 and Sunday is 7, in the format YYYY-Www-D
(or omitting hyphen, YYYYWwwD
) such as 2014-W07-2
(a Tuesday in 7th week of year). The W
is important to disambiguate from a year-month such as 2014-07
being July of 2014.
The java.time package built into Java 8 and later is inspired by Joda-Time but entirely re-architected. See Tutorial.
In java.time, an Instant
is a moment on the timeline in UTC. Apply a time zone (ZoneId
) to get a ZonedDateTime
. Use LocalDate
to get a date-only value with no time-of-day and no time zone.
Note that determining the first moment of a day in java.time requires an extra step when compared to Joda-Time: We must go through the LocalDate
class to call its atStartOfDay
method.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
LocalDate firstDayOfThisWeek = now.toLocalDate ().with ( DayOfWeek.MONDAY );
LocalDate firstDayOfNextWeek = firstDayOfThisWeek.plusWeeks ( 1 );
ZonedDateTime thisWeekStart = firstDayOfThisWeek.atStartOfDay ( zoneId );
ZonedDateTime nextWeekStart = firstDayOfNextWeek.atStartOfDay ( zoneId );
Unfortunately, java.time lacks the equivalent of Joda-Time's Interval
.
Fortunately we have ThreeTen Extra, the project that extends java.time (310 being the number of the JSR defining java.time). This library includes an Interval
class that integrates with java.time. This Interval
class is more limited than that of Joda-Time as it supports only Instant
objects without time zones (always in UTC).
Caution: The ThreeTen-Extra project reserves the right to change its interfaces and/or implementations. While intended to be useful as-is, it also serves as an experimental proving ground for classes that may be eventually incorporated into java.time. I gladly make use of ThreeTen-Extra, but you must make your own risk-benefit decision.
// This next line requires adding the `ThreeTen Extra` library to your project.
Interval interval = Interval.of ( thisWeekStart.toInstant () , nextWeekStart.toInstant () ); // "Interval" is part of ThreeTen-Extra project, not built into Java 8.
Dump to console.
System.out.println ( "now: " + now + " thisWeekStart: " + thisWeekStart + " nextWeekStart: " + nextWeekStart + " interval: " + interval );
now: 2016-01-15T18:10:48.143-05:00[America/Montreal] thisWeekStart: 2016-01-11T00:00-05:00[America/Montreal] nextWeekStart: 2016-01-18T00:00-05:00[America/Montreal] interval: 2016-01-11T05:00:00Z/2016-01-18T05:00:00Z
You can determine the week-of-year as defined by the ISO 8601 standard. Note the "week based" terms. Near the beginning or ending of the year, a date will be in one calendar year while its ISO 8601 week’s year may be ±1.
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
int weekOfYear = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekBasedYear = now.get ( IsoFields.WEEK_BASED_YEAR );
System.out.println ( "weekOfYear: " + weekOfYear + " of weekBasedYear: " + weekBasedYear );
weekOfYear: 2 of weekBasedYear: 2016
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.
UPDATE: The Joda-Time project is now in maintenance mode and advises migration to the java.time classes. I am leaving this section intact as history.
The Joda-Time 2.5 library offers the Interval
class to represent a span of time as a pair of specific moments in time along the timeline of the Universe. Each moment is represented by the DateTime
class.
Joda-Time uses the Half-Open [)
approach to defining spans of time. The beginning is inclusive while the ending is exclusive. This is generally the best way to work with such spans of time. Search StackOverflow for many examples and discussions.
Joda-Time uses the ISO 8601 definition of weeks. Also, Joda-Time uses ISO 8601 as its defaults for parsing and generating string representations of date-time values.
DateTimeZone zone = DateTimeZone( "America/Montreal" );
// Get first moment of a Monday. Inclusive.
DateTime start = new DateTime( 2014, 11, 24, 0, 0, 0, zone ); // Handle exception thrown if occurring during a Daylight Saving Time gap.
DateTime stop = start.plusWeeks( 1 ); // First moment of following Monday. Exclusive.
Interval week = new Interval ( start, stop );
Search StackOverflow for many questions and answers on finding the first Monday of a week.
LocalDate
(date-only)While you might well be tempted to use LocalDate
objects (date only, no time-of-day) to build an Interval
. That would be sensible and useful. Unfortunately, the implementation of Interval
supports only DateTime
objects, not LocalDate
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With