String date = "2015-40";
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("YYYY-ww")
.parseDefaulting(ChronoField.DAY_OF_WEEK, DayOfWeek.MONDAY.getValue())
.toFormatter(Locale.FRANCE);
LocalDate ld = LocalDate.parse(date, formatter);
System.out.println(ld);
Sorry that I can write only Java, I trust you to translate to Scala. Output is:
2015-09-28
Why were you getting an exception? There were a couple of things missing for us to parse 2015-40
into a LocalDate
:
- A
LocalDate
is a calendar date, and week 40 consists of 7 days. Java doesn’t know which of those 7 days you want and refuses to make the choice for you. In my code above I have specified Monday. Any other day of the week should work.
- A bit subtler. While to a human year 2015 and week 40 is unambiguous, the same is not always the case around New Year where week 1 may begin before New Year or week 52 or 53 extend after New Year. So a calendar year and a week number don’t always define one specific week. Instead we need the concept of a week year or week-based year. A week year lasts from week 1 inclusive no matter if that means it begins a few days before or after New Year. And it lasts until the last day of the last week, again most often a few days before or after New Year. To tell a
DateTimeFormatter
that we want to parse (or print) the week year we need to use upper case YYYY
instead of lower case yyyy
(or uuuu
).
As an aside, if you can influence the format, consider 2015-W40
with a W
. This is ISO 8601 format for year and week. In ISO 2015-12
denotes year and month, and many will read it this way. So to disambiguate and avoid misreading.
Edit:
In my explanation I have assumed ISO week scheme (Monday is the first day of week and week 1 is defined as the first week having at least 4 days in the new year). You may pass a different locale to the formatter builder to obtain a different week scheme.
If you are sure that your weeks follow ISO, Andreas’ suggestion in the comment is good enough that we want as part of the answer:
Alternatively, add the ThreeTen Extra library, so you can use the
YearWeek
class, that has a nice atDay?(DayOfWeek dayOfWeek)
method for getting a LocalDate
.
Link: Wikipedia article: ISO 8601
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…