Rectangle 27 1

As @Ole V.V. explained, you need to define in what day the week starts, and how many days it must have to be considered the first week.

  • The minimal number of days in the first week: the standard counts the first week as needing at least 4 days

The month is divided into periods where each period starts on the defined first day-of-week. The earliest period in the same month is referred to as week 0 if it has less than the minimal number of days and week 1 if it has at least the minimal number of days.

Depending on how you define those, you can have different results. Consider the calendar for July 2017:

July 2017
Su Mo Tu We Th Fr Sa
                   1
 2  3  4  5  6  7  8
 9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

If we consider first day of week as Sunday and minimal number of days in the first week as 1, we have:

Calendar

If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).

The code below works for both. The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.

I'm using a DateTimeFormatter because it takes all the fields (month, year, day of week and week of month) and resolves the day accordingly, creating a LocalDate (which has the day/month/year fields). I'm also using the WeekFields class, which can be configured to use different week definitions (first day and minimal number of days in first week)

There's also a little adjustment to consider Sunday as zero:

Using this code (week starts on Sunday, and 2 days are required to be considered the first week - otherwise week will be zero as in the first example above):

LocalDate d = getDate(1, 6, 7, 2017);

d will be 2017-07-08 (Saturday in the week 1 of July 2017).

If you want to use ISO 8601 definition, use the constant WeekFields.ISO instead of using WeekFields.of() method.

As @Ole V.V. suggested in the comments, it can also be done without creating a formatter: get the first dayOfWeek of the month and adjust it to the desired weekOfMonth:

public LocalDate getDate(int weekOfMonth, int dayOfWeek, int month, int year) {
    // you can customize your week definition (first day of week and mininum days in first week)
    WeekFields wf = WeekFields.of(DayOfWeek.SUNDAY, 2);

    // Sunday is 0, adjusting value
    DayOfWeek dow = DayOfWeek.of(dayOfWeek == 0 ? 7 : dayOfWeek);

    // get the first weekday of the month
    LocalDate first = LocalDate.of(year, month, 1).with(TemporalAdjusters.nextOrSame(dow));

    // check in which week this date is
    int week = first.get(wf.weekOfMonth());

    // adjust to weekOfMonth
    return first.plusWeeks(weekOfMonth - week);
}

This works exactly the same way, but without the need of a formatter - I've tested with dates from year 1600 to 2100 and it gets the same results.

PS: Calendar also has a similar configuration via the methods setFirstDayOfWeek() and setMinimalDaysInFirstWeek(). You can check the default configuration calling the respective get methods.

Ah, the WeekFields class, of course. Thanks. Couldnt it be done without building a string and parsing it? I think I would try getting the week number of the first Thursday of the month (for example; which day-of-week was required) using WeekFields.weekOfMonth(). Then add the appropriate number of weeks using LocalDate.plusWeeks().

@OleV.V. I haven't tried without a formatter yet. Let's see if it works, I'll update the answer if I find a way. Thanks! - I used a formatter because it already resolves the day based on the other fields, but let's see if it can be done in another way...

@OleV.V. Done! Indeed, it's much better than using a formatter, thanks a lot!

I am very fond of the cooperation you and I are having, Hugo. Two minds think better than one.

How to determine the date passing the Week Number and Day Number (Week...

java date calendar gregorian-calendar date-parsing