Question

My issue is seemingly extremely simple. I make a calendar graphic user interface, from a GregorianCalendar object, and uses it's methods to calculate the correct number of days in the different months, and the different date's corresponding weekdays.

But the weekdays are consistentyl one day off. The Calendar claims that the 1st of July 2013 is a '2', which in my part of the world means tuesday. It should have been a '1' for Monday. "Easy!" i think, and put in the line: c.setFirstDayOfWeek(Calendar.MONDAY); But no reaction is given.

So I search stackoverflow for an answer, but everyone with my problem seem to have forgotten that January is 0, and not 1. I haven't. So now I am stuck.

As a simplifyed code, I have made a very short code piece, with it's corresponding output:

    GregorianCalendar c = new GregorianCalendar();
    c.setFirstDayOfWeek(Calendar.MONDAY);
    c.set(Calendar.MONTH, 6);
    c.set(Calendar.DAY_OF_MONTH, 1);
    c.set(Calendar.YEAR, 2013);

    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-YYYY");
    System.out.println(sdf.format(c.getTime()));
    System.out.println(c.get(Calendar.DAY_OF_WEEK));

and the output is:

01-07-2013

2

I refuse to put in a "-1" in my code, to wrongly correct the symptoms of what is obviously a mistake. Help is appreciated.

Was it helpful?

Solution 2

I refuse to put in a "-1" in my code, to wrongly correct the symptoms of what is obviously a mistake.

The mistake is your assumption that Calendar.get(Calendar.DAY_OF_WEEK) is localized. It isn't. The mapping between day-of-week and number is fixed; use Calendar.getFirstDayOfWeek() to determine the human understanding of "first day of the week" if you need to; I'd be surprised if you really wanted to show a user "2" anyway... surely you'd want to show them the name of the day of the week.

Any calculations involving the start of the week should use getFirstDayOfWeek though.

OTHER TIPS

Yes, date handling in Java is problematic...

  • Months start from 0 (JANUARY)
  • days of week start from SUNDAY being 1, SATURDAY being seven (Ideone fiddle)
  • c.setFirstDayOfWeek(Calendar.MONDAY); is a bit different than what the name suggests

    The first week of a month or year is defined as the earliest seven day period beginning on getFirstDayOfWeek() and containing at least getMinimalDaysInFirstWeek() days of that month or year

You can get out of troubles by always using the constants defined in the Calendar class, and not even trying to deduce any meaning from the numerical representations of those constants, or the results returned by the Calendar.get(int) method...

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

The first day of the week is Locale dependent

Demo:

import java.time.format.TextStyle;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // ############## First day of week ##############
        System.out.println(WeekFields.of(Locale.UK).getFirstDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH));
        System.out.println(WeekFields.of(Locale.US).getFirstDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH));
    }
}

Output:

Monday
Sunday

ONLINE DEMO

How to get the day-of-week?

import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.time.format.TextStyle;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2013, Month.JULY, 1);
        System.out.println(date);

        // ############ Day of week ############
        System.out.println(date.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.ENGLISH));
        // Alternatively,
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE", Locale.ENGLISH);
        System.out.println(date.format(dtf));
    }
}

Output on my system in Europe/London timezone:

2013-07-01
Monday
Monday

ONLINE DEMO

Learn more about the modern Date-Time API* from Trail: Date Time.

What went wrong with your code and expectation?

  • The thing that went wrong with your expectation is that you assumed c.get(Calendar.DAY_OF_WEEK) would give you the first day of the week whereas it returns the value representing MONDAY because it was Monday on the 1st Jul 2013.

  • The thing that is wrong with your code is the use of Y (Week year) instead of y (Year). Check this discussion to learn more about this difference.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

java.time

I recommend that you use java.time, the modern Java date and time API, for your date work. Arvind Kumar Avinash has already in an answer shown a nice application of it (+1).

The way I understand your question you want Monday to be the first day of the week, and you want to know which number day of the week a certain date is (e.g., July 1, 2013). Monday = 1, Tuesday = 2 and so forth up to Sunday = 7.

    LocalDate ld = LocalDate.of(2013, Month.JULY, 1);
    
    // Monday is first day of week; which number day of the week is ld then?
    int numberDayOfTheWeek = ld.get(WeekFields.ISO.dayOfWeek()); // 1 through 7
    System.out.println(numberDayOfTheWeek);

Output is:

1

Having Monday be the first day of the week agrees with ISO 8601, the international standard for dates and times. So the built-in WeekFields.ISO uses this numbering. WeekFields.ISO.dayOfWeek() gives us a TemporalField that we then use for querying the LocalDate object about its day of the week.

Instead of WeekFields.ISO we may use WeekFields.of(DayOfWeek.MONDAY, 1) to specify that Monday is the first day of the week. The second argument to of() is the minimal number of days in the first week (of the year or month) form 1 through 7, which we don’t use here, so it doesn’t matter which number we use.

Link

This is one of the caveats in Java,

DAY_OF_WEEK,

This field takes values SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, and SATURDAY.

When your program prints 2, it's telling you that the day of week is MONDAY. This constant value has nothing to do with the beginning of the week. It does coincidentally happen to be the same as the day of the week if the first day of the week is SUNDAY - but it doesn't change if the first day of the week is redefined.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top