I am looking to build up a function that return an array with all week numbers of the previous months in a year that are the same week number of one particular month.
I am using as first day of week Monday and I am taking as first week of month week with the first Monday of current month.
Input: week of year and year. For example, 27 and 2019. The first week of July (7).
Output: array of week of months. For example, [2, 6, 10, 14, 19, 23, 27].
What I try:
private void getResult(int weekYear)
{
LocalDate date = LocalDate.now();
final int weekNumber = 27;
LocalDate newDate = date.with(IsoFields.WEEK_OF_WEEK_BASED_YEAR, weekNumber);
int month = newDate.getMonthValue();;
int weekMonth = LocalDate.from(newDate).get(WeekFields.ISO.weekOfMonth());
System.out.println(newDate);
System.out.println(month);
System.out.println(weekMonth);
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 1; i <= month; i++)
{
LocalDate tempDate = date.withYear(2019).withMonth(i).with(WeekFields.ISO.weekOfMonth(), weekMonth);
int tempYear = LocalDate.from(tempDate).get(WeekFields.ISO.weekOfWeekBasedYear());
list.add(tempYear);
}
list.forEach((e) -> System.out.print(e + " "));
}
int weekYear = 27;
getResult(weekYear);
What I get: [1 6 10 14 18 23 27].
What I am looking for: I have two question:
I think the key here is understanding a few points (hope that I have understood them correctly from your question).
the results obtained are different from those expected. I think the problem is due to the fact that I didn't specify how to calculate the first week of the month (first Monday of the month). Is it right? How can I solve that?
I believe you are correct. To count the Mondays of the month you may use:
LocalDate tempDate = date.withYear(2019)
.withMonth(i)
.with(ChronoField.DAY_OF_WEEK, DayOfWeek.MONDAY.getValue())
.with(ChronoField.ALIGNED_WEEK_OF_MONTH, weekMonth);
(DayOfWeek.MONDAY.getValue()
is just of wordy way of saying 1
, of course, but conveys the intention better, so I prefer it.)
With this change to your code the output is the expected:
2 6 10 14 19 23 27
The key is ChronoField.ALIGNED_WEEK_OF_MONTH
. The aligned weeks of a month start from the 1st of the month and are always 7 days regardless of the days of the week. The first aligned week is from the 1st through the 7th of the month, the 2nd aligned week if from 8th through 14th, etc. Since we have set the day of week to Monday, setting the aligned week to 1 gives us the 1st Monday of the month, etc.
We’re done yet, though. If I set weekNumber
to 40, I get
2 6 10 14 14 23 27 27 36 41
I had expected 40 to be the last number in the list, but it is not there. Week 40 of 2019 is from Monday September 30 through October 6, so if I understand correctly you want the 5th week of those months that have a 5th week. This brings us back to the issue of not all month having a week 5 (because they don’t have 5 Mondays). What happened was that since I ran your code on a Tuesday, it took Tuesday in week 40, which is October 1, as a starting point, and therefore gave me the 1st rather than the 5th week of every month.
are there better solutions? Can you suggest one?
I can’t really. I think that what you’ve got is fine.
Only you’re not using the int weekYear
parameter. You may want to use it in place of your weekNumber
local variable. In any case you should delete one of them and use the other.
And this unrelated tip: Your use of LocalDate.from(someLocalDate)
is redundant since it just gives you the same LocalDate
again (either the same object or an equal one, I don’t know or care). Just use someLocalDate
in those situations.