1

Given:

  • A Year: 2019
  • A Calender Week Number: 1 (== 1st Week of a year)
  • A DayOfWeek: SUNDAY

Needed:

A transformation f of those Infos into a LocalDate Object so that

assertEquals(LocalDate.of(2019,1,6), f(2019,1,SUNDAY))

What I tried

I did not find a way with java.time.* to create a Date from an Info like "The Sunday of the first calender week in 2019". I found that the old java.util.Calendar class had a setWeekDate() function that could be usefull. But the following code caused an Exception:

    ...
    Calendar c = Calendar.getInstance();
    c.setWeekDate(2019, 1, Calendar.MONDAY);
    c.setTimeZone(TimeZone.getDefault());

    return LocalDate.from(c.toInstant());

java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: 2018-01-08T20:03:55.602Z of type java.time.Instant
at java.time.LocalDate.from(LocalDate.java:379)
at ...
KFleischer
  • 942
  • 2
  • 11
  • 33
  • 1
    "1st Week of a year" - Does this week start on January 1? – Jacob G. Feb 20 '19 at 20:39
  • You don’t want to use the poorly designed and long outdated `Calendar` class. java.time offers all the functionality you need. However, as @JacobG. hinted, you need to define “calendar week number” since more than one standard exists. – Ole V.V. Feb 21 '19 at 07:51
  • @Mika's solution was what I needed. – KFleischer Feb 21 '19 at 09:34

1 Answers1

5

Check ChronoField or IsoFields for a suitable way to get week for the calendar system that you want to use. LocalDate object that is used as "base" value should have a week value of the expected year.

int year = 2019;
int weekNumber = 1;
LocalDate localDate = LocalDate.of(year, 2, 1)
        .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber)
        .with(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue());

Selecting first date is meaningful. Using LocalDate.of(year, 1, 1) would give a day that can belong to last week of the previous year, same goes for LocalDate.now()but only for given period of time.

LocalDate.of(2017, 1, 1)
    .with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 26)
    .with(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue());
// 2016-07-03

LocalDate.of(2017, 1, 1).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
// 52

So jumping from week 52 to week 26 would give date of 2016-07-03 because date is calculated by subtracking time between weeks 52 and 26.

Also see answer here for more discussion about withYear: Unexpected date calculation result

Mika
  • 1,256
  • 13
  • 18
  • Interesting. Didn't even know IsoFields and ChronoField existed. Thanks! – LppEdd Feb 20 '19 at 23:43
  • 1
    This does not work! Check 2017/26 as example. You need to create the LocalDate by LocalDate.now().with(2019) See: https://stackoverflow.com/questions/47259213/unexpected-date-calculation-result/54870642 – KFleischer Feb 25 '19 at 19:11
  • @KFleischer Great finding! – Mika Feb 26 '19 at 17:45