I'm trying to figure out how to determine whether a particular Monday is the first, second, third or fourth Monday of a given month. I've figured out how to get the next Monday and the Week of the of month that resides in using the LocalDate class.
LocalDate now = LocalDate.of(2018, 2, 1);
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int week = nextMonday.get(weekFields.weekOfMonth());
Case in the example above, the code gets the next Monday and the week it resides in. Week is the second week of Feb, but that Monday is not the second Monday, it's the first. Any help with this would be greatly appreciated.
You should not use your own arithmetic for this. Use the built-in functionality:
int week = nextMonday.get(ChronoField.ALIGNED_WEEK_OF_MONTH);
With the date from your code this yields:
1
Which means that the Monday you got (February 5) is the 1st Monday of the month. Also you don’t need any WeekFields
because the first Monday of the month is the first Monday of the month no matter which day is the first day of week, or how weeks of the year are numbered.
Date arithmetic is often complicated and easy to get wrong. Which also means that even if you finally get your calculation right, it is hard for a reader to convince herself/himself that your code is correct. So it is always better to use the built-in functionality that we trust to be tested and which uses explanatory names rather than numbers like 1 and 7.
You may be surprised that the field to use is called ALIGNED_WEEK_OF_MONTH
. Think of aligned weeks as a week that begins on the 1st of the month no matter the day-of-week, and the following weeks right after each other. In February 2018, the first aligned week goes from Thursday, Feb 1 to Wednesday, Feb 7. The following aligned weeks begin on Thursdays Feb 8, Feb 15 and Feb 22. Obviously the first Monday of the month falls in aligned week 1, the 2nd Monday in aligned week 2, etc. Therefore it works to use ALIGNED_WEEK_OF_MONTH
.
Edit: You should take Ole V. V's answer (ChronoField.ALIGNED_WEEK_OF_MONTH
) instead of this answer.
You could figure out what day of the month it is, divide by 7, and add 1:
LocalDate nextMonday = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((nextMonday.getDayOfMonth()-1) / 7) +1;
For example, this code:
LocalDate now = LocalDate.of(2018, 2, 1);
for(int i = 0; i < 10; i++) {
now = now.with(next(DayOfWeek.MONDAY));
int weekNo = ((now.getDayOfMonth()-1) / 7) +1;
System.out.println("Date : " + now + " == " + weekNo);
}
Prints out the following, which is what I believe you want...
Date : 2018-02-05 == 1
Date : 2018-02-12 == 2
Date : 2018-02-19 == 3
Date : 2018-02-26 == 4
Date : 2018-03-05 == 1
Date : 2018-03-12 == 2
Date : 2018-03-19 == 3
Date : 2018-03-26 == 4
Date : 2018-04-02 == 1
Date : 2018-04-09 == 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With