3

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;
}
input
  • 7,503
  • 25
  • 93
  • 150
  • 1
    What problems are you getting?? Any unexpected output?? We cannot figure out with just one method.. – Rohit Jain Oct 01 '12 at 15:22
  • 1
    Basically you want to know how many weeks does a month have if you say, for example, that a week starts on wednesday instead of sunday? With this in mind, the code you show returns your expected behaviour for the default value (sunday)?. – Fritz Oct 01 '12 at 15:25
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html), and `java.text.SimpleTextFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Sep 09 '17 at 22:19

3 Answers3

3

Try to set the first day of the week first:

Calendar.setFirstDayOfWeek()

Benoît Bouré
  • 1,017
  • 9
  • 18
2

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);
Fritz
  • 9,987
  • 4
  • 30
  • 49
2

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

calendar of month of September 2017 showing calendar starting with Monday August 28 to Monday October 2.


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?

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154