tl;dr
If you mean a standard ISO 8601 week, use the YearWeek
class from the ThreeTen-Extra library.
For specific week number in specific week-based year:
YearWeek.of( // Standard ISO 8601 week, where week # 1 has the first Thursday of the calendar year, and runs Monday-Sunday.
2018 , // Week-based year, NOT calendar year.
37 // Week-of-week-based-year. Runs 1-52 or 1-53.
)
.atDay( DayOfWeek.MONDAY ) // Returns a `LocalDate` object.
➡ Trap for java.time.DateTimeException
if the input is not valid, if there is no such week in that week-based-year.
For current week:
YearWeek.now( // Standard ISO 8601 week, where week # 1 has the first Thursday of the calendar year, and runs Monday-Sunday.
ZoneId.of( "Pacific/Auckland" ) // Determining a week means determining a date, and that requires a time zone. For any given moment, the date varies around the globe by zone.
)
.atDay( DayOfWeek.MONDAY ) // Returns a `LocalDate` object.
Define “week”
Define what you mean by “week”. Is week # 1 the one with January 1st? Is week # 1 the first to have all seven days composed of days in the new year? If so, what is the first-last days of the week, Sunday-Saturday or Monday-Sunday or something else? Or is week # 1 the first to have a certain day of the week?
The troublesome old date-time classes defined a week by depending on Locale
. If you fail to specify a Locale
, the JVM’s current default Locale
is silently implicitly applied. So your results can vary at runtime.
If possible I recommend using the standard ISO 8601 week definition. The week runs from Monday-Sunday, and week # 1 contains the first Thursday of the calendar year. So there are either 52 or 53 weeks per year.
Getting the current week means getting the current date. A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-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" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
If you simply want a certain day-of-week on or before that date, then never mind about the week. Use a TemporalAdjuster
implementation found in TemporalAjdusters
. Specify your day-of-week via the DayOfWeek
enum.
LocalDate mondayOnOrBeforeToday = today.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ) ;
ThreeTen-Extra library
If you do want to work with ISO 8601 weeks, there is limited support available in the IsoFields
class. But I recommend instead that you add the ThreeTen-Extra library to your project. That library provides additional date-time classes that complement those built into Java SE 8 and later. In particular, you get the YearWeek
class.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
YearWeek yw = YearWeek.now( z ) ;
Ask for the LocalDate
of a day-of-week in that week.
LocalDate ld = yw.atDay( DayOfWeek.MONDAY ) ;
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.