I am using a custom calendar in my app. I have given the users option to select the first day of the week which could be: Saturday, Sunday, Monday
I want to get the number of weeks in a month - depending on when the week starts, overriding the default value of week start - Sunday
.
Code:
public int getWeeksOfMonth(int year, int month) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, month-1);
calendar.set(Calendar.YEAR, year);
int numOfWeeksInMonth = calendar.getActualMaximum(Calendar.WEEK_OF_MONTH);
return numOfWeeksInMonth;
}
Try
calendar.setFirstDayOfWeek(Calendar.MONDAY); //sets first day to monday, for example.
In your case you might want to do this:
public int getWeeksOfMonth(int year, int month, int weekStart) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, month-1);
calendar.set(Calendar.YEAR, year);
calendar.setFirstDayOfWeek(weekStart);
int numOfWeeksInMonth = calendar.getActualMaximum(Calendar.WEEK_OF_MONTH);
return numOfWeeksInMonth;
}
And call the method with a line such as
int weeks = getWeeksOfMonth(2012, 5, Calendar.WEDNESDAY);
Try to set the first day of the week first:
Calendar.setFirstDayOfWeek()
tl;dr
ChronoUnit.WEEKS.between( calendarStart , calendarStop )
Avoid legacy classes
Avoid the troublesome old date-time classes that are now legacy, supplanted by the modern java.time classes.
java.time
Track the day-of-week by using the DayOfWeek
enum.
DayOfWeek firstDayOfWeek = DayOfWeek.MONDAY ;
Get the month you are interested in, represented by a YearMonth
. Perhaps the current month. For current month, you must specify the desired/expected time zone as for any given moment the date may vary around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
YearMonth ym = YearMonth.now( z ) ;
Get first and last day of the month.
LocalDate monthStart = ym.atDay( 1 ) ;
LocalDate monthStop = ym.atEndOfMonth() ;
Get date for the day-of-week. For that, use a TemporalAdjuster
, one provided by the TemporalAdjusters
class (note the plural s
).
Spans of time in java.time are wisely defined using Half-Open approach, where the beginning is inclusive while the ending is exclusive. So note how we need to get the date of the desired day-of-week after the end of the month. If the end-of-month happened to itself be the desired day-of-week, we need to go past it.
LocalDate calendarStart = monthStart.with( TemporalAdjusters.previousOrSame( firstDayOfWeek ) ) ;
LocalDate calendarStop = monthStop.with( TemporalAdjusters.next( firstDayOfWeek ) ) ;
Calculate the number of weeks between.
long weeks = ChronoUnit.WEEKS.between( calendarStart , calendarStop ) ;
See this code run live at IdeOne.com.
firstDayOfWeek: MONDAY
ym: 2017-09
month: 2017-09-01/2017-09-30
calendar: 2017-08-28/2017-10-02
weeks: 5
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
- Java SE 8, Java SE 9, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
- See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.