1

I am trying to determine what day of the week is the first day of the month but for some reason it is not returning me the correct day of the week.

Here is my code below:

CalendarMonth[] months = CalendarUtils.constructMonthViewArray(new GregorianCalendar());


    public static CalendarMonth[] constructMonthViewArray(Calendar cal) {
        CalendarMonth[] months = new CalendarMonth[CALENDAR_GRID_SIZE];


        int year = cal.get(cal.YEAR);
        int month = cal.get(cal.MONTH);;
        // calculate how many days in the month
        int numOfDays = getNumOfDaysInMonth(cal);
        // calculate what day(mon-sunday) is the 1st of the month
        int firstDayOfMonth = getFirstDayOfMonth(cal);



private static int getFirstDayOfMonth(Calendar cal) {
        int firstDay = cal.get(Calendar.DAY_OF_WEEK);

        Log.d(TAG, "");

        // decrement it because our array deals with values 0-6(indexes)
        firstDay--;


        if (firstDay == 0) {
            firstDay = 6;
        } else {
            // decrement again so that the days start from 0.
            firstDay--;
        }
        return firstDay;
    }

The line from "int firstDay = cal.get(Calendar.DAY_OF_WEEK);" fails to give me the correct day of the week and returns the value 2 for getting the 1st day of this month(January 2011) when the first of the month was on a Saturday(7).

Am I missing something? I have debugged and checked what month, year and date the cal variable is set and it indeed indicated today's date as corrected but when i get the day of week it doesn't get the value 7.

midhunhk
  • 5,560
  • 7
  • 52
  • 83
Jono
  • 17,341
  • 48
  • 135
  • 217

3 Answers3

12

I can't reproduce the problem you're seeing. As Michael says, there's a lot of code you haven't shown us, but Calendar.getDayOfWeek definitely works:

import java.util.*;

public class Test {
    public static void main(String[] args) {
        Calendar calendar = new GregorianCalendar();
        calendar.set(2011, 0, 1); // 0 = January
        System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // Prints 7
    }
}

Did you maybe forget that months are 0-based in java.util.Calendar?

If you can produce a similar short but complete program which shows the wrong day of the week, please post it.

The fact that you're decrementing firstDay twice within getFirstDayOfMonth seems somewhat odd, as well as the fact that it doesn't really reflect the name of the method (as Michael mentioned).

Finally, my constant recommendation for Java date/time handling: if you can possibly use Joda Time instead of java.util.Calendar, do so. It's a much, much better API.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    Urgggh ... months are 0 based, but days are not ... 1 hour of my life wasted. Day's of week finally works +1 for that. – Drejc Jun 28 '11 at 12:01
  • @Drejc The *java.time* classes that supplanted `Calendar` use sane numbering, 1-12 for January-December, 1-7 for Monday-Sunday, and `2018` means year 2018. One of *many* reasons to migrate away from the legacy date-time classes. – Basil Bourque Oct 06 '18 at 21:19
0

tl;dr

Convert from terrible legacy classes (Calendar, GregorianCalendar, etc.) to modern java.time classes (ZonedDateTime, LocalDate, etc.). Then get object for day-of-week, and ask it to automatically localize the name of that day of the week.

(GregorianCalendar) myJavaUtilCalendar   // Cast your `Calendar` to `GregorianCalendar` assuming it actually is one.
.toZonedDateTime()                       // Convert from legacy class to modern class.
.toLocalDate()                           // Extract date-only object, without time-of-day and without time zone.
.with(                                   // Adjust to another date by calling `TemporalAdjuster` implementation such as are found in `TemporalAdjusters` class.
    TemporalAdjusters.firstDayOfMonth()  // Adjust to the first day of the month.
)                                        // Returns another `LocalDate` object, for the first of the month.
.getDayOfWeek()                          // Obtain a `DayOfWeek` enum object, one of seven pre-defined objects representing each day of the week.
.getDisplayName(                         // Automatically localize.
    TextStyle.FULL ,                     // Specify how long or abbreviated.
    Locale.CANADA_FRENCH                 // Or `Locale.US` etc. to specify the human language and cultural norms to use in localizing.
)                                        // Returns text in a `String` such as “Monday” or “lundi”.

java.time

The java.util.Calendar/.Date and related classes are a confusing mess as you have learned the hard way.

The modern approach uses java.time classes.

Conversion

If starting with a java.util.Calendar object, convert to java.time.

An Instant is a moment on the timeline in UTC.

Instant instant = myJavaUtilCalendarObject.toInstant();

Apply a time zone in order to get a date in order to get a day-of-week.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );

Note that a time zone is critical in determining a date (and therefore day-of-week). "Today" is not the same date everywhere in the world simultaneously. A new day dawns earlier, for example, in Paris than in Montréal.

First Day Of Month

Let's move to the first of the month by calling withDayOfMonth.

ZonedDateTime zdtFirstOfMonth = zdt.withDayOfMonth(1);

Note that moving a date-time to first of month has issues. Anomalies such as Daylight Saving Time (DST) could have a surprising effect. Read the doc so you understand the behavior.

DayOfWeek

For day of week, use the well-named DayOfWeek enum.

DayOfWeek dayOfWeek = zdtFirstOfMonth.getDayOfWeek();

I suggest passing instances of this enum rather than a magic number like 2, 7, etc. But if you insist, you can extract an integer.

int dayOfWeekNumber = dayOfWeek.getValue();

To get a String of the name of day-of-week, let java.time generate a localized String via the getDisplayName method.

String output = dayOfWeek.getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH );  // Or Locale.ENGLISH

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.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

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
0

The code of getFirstDayOfMonth() appears not to do what the method name says at all - but to actually understand what is happening, we need to see all the code that is involved, especially how the calendar initialized and the code of getNumOfDaysInMonth()

One thing to keep in mind: what is considered the first day of the week depends on the locale, as per getFirstDayOfWeek()

Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
  • Specifically if you call getFirstDayOfMonth(new Calendar()) you'd get the day of the current date and not the first day of the month. – Guss Jan 10 '11 at 10:19
  • @Guss: You can't do `new Calendar()`. You probably meant `Calendar.getInstance()` – Goran Jovic Jan 10 '11 at 10:46