1

I was testing a piece of our date management framework which is supposed to reset some Calendar fields (using actual minimum).

However, when changing first day of week, Calendar always return SUNDAY (1) as actual minimum for day of weeks. Is it a bug ?

MVCE:

import java.util.*;

public class Main {
  public static void main(String[] args) {
    System.out.printf("Java specification: %s%n", System.getProperty("java.vm.specification.version"));
    System.out.printf("Java version: %s%n", System.getProperty("java.specification.version"));
    System.out.printf("VM version: %s%n", System.getProperty("java.vm.version"));

    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

    int[] days = { 1, 5, 7 };
    for (int day : days) {
      cal.setTimeInMillis(0L);
      cal.setFirstDayOfWeek(day);
      System.out.printf("expected: %d, actual: %d%n", day, cal.getActualMinimum(Calendar.DAY_OF_WEEK));
    }
  }
}
Community
  • 1
  • 1
LoganMzz
  • 1,597
  • 3
  • 18
  • 31
  • 1
    It is not a bug. the day of the week depends on the Locale of your environment. en_US have the first day of the week set to Sunday. Duplicated: http://stackoverflow.com/questions/269486/how-to-specify-firstdayofweek-for-java-util-calendar-using-a-jvm-argument#answer-269538 – Didac Montero Apr 07 '15 at 09:49
  • I have changed first day of week ... – LoganMzz Apr 07 '15 at 09:53
  • 1
    I think first day of week isn't the same as actual minimum. You have getFirstDayOfWeek() method for that. – notanormie Apr 07 '15 at 09:57

2 Answers2

4

You should use cal.getFirstDayOfWeek() instand of cal.getActualMinimum(Calendar.DAY_OF_WEEK)

because cal.getActualMinimum(Calendar.DAY_OF_WEEK) will always return sunday look at the implementation of the getActualMinimum(Calendar.DAY_OF_WEEK) in java source code

  public int getActualMinimum(int field) {
        if (field == DAY_OF_MONTH) {
            GregorianCalendar gc = getNormalizedCalendar();
            int year = gc.cdate.getNormalizedYear();
            if (year == gregorianCutoverYear || year == gregorianCutoverYearJulian) {
                long month1 = getFixedDateMonth1(gc.cdate, gc.calsys.getFixedDate(gc.cdate));
                BaseCalendar.Date d = getCalendarDate(month1);
                return d.getDayOfMonth();
            }
        }
        return getMinimum(field);
    }

And getMinimum is :-

   public int getMinimum(int field) {
        return MIN_VALUES[field];
    }

and MIN_VALUES array is defined as :-

 static final int MIN_VALUES[] = {
        BCE,            // ERA
        1,              // YEAR
        JANUARY,        // MONTH
        1,              // WEEK_OF_YEAR
        0,              // WEEK_OF_MONTH
        1,              // DAY_OF_MONTH
        1,              // DAY_OF_YEAR
        SUNDAY,         // DAY_OF_WEEK
        1,              // DAY_OF_WEEK_IN_MONTH
        AM,             // AM_PM
        0,              // HOUR
        0,              // HOUR_OF_DAY
        0,              // MINUTE
        0,              // SECOND
        0,              // MILLISECOND
        -13*ONE_HOUR,   // ZONE_OFFSET (UNIX compatibility)
        0               // DST_OFFSET
    };
Keval
  • 1,857
  • 16
  • 26
  • Ok, i was thinking about minimum as value for rolling, not just the value bound you can have with get/set. – LoganMzz Apr 07 '15 at 10:26
0

The Answer by K M PATEL is correct.

Both the Question and the Answer use outmoded classes. The old date-time classes bundled with the earliest version of Java have been supplanted by the java.time classes.

Standard definition

The DayOfWeek enum defines a week according to the ISO 8601 standard, with Monday being 1 and Sunday being 7.

You can ask a DayOfWeek object for this 1-7 number.

int dayOfWeekNumber = DayOfWeek.WEDNESDAY.getValue();

But do not pass this number around your code. Instead pass around DayOfWeek objects to enjoy the benefits of type-safety and guaranteed valid values.

Localized definition

For localized definitions of the day-of-week, week-of-month and week-of-year fields, use the WeekFields class.

WeekFields weekFields_US = WeekFields.of ( Locale.US );
DayOfWeek firstDayOfWeek = weekFields_US.getFirstDayOfWeek ();

Dump to console.

System.out.println ( "weekFields_US: " + weekFields_US + " | firstDayOfWeek: " + firstDayOfWeek );

weekFields_US: WeekFields[SUNDAY,1] | firstDayOfWeek: SUNDAY

Define your own week variation

I suggest sticking with specifying Locale objects to define the week. But if you insist, you can define your own variation of the week. Call WeekFields.of and specify (a) the first day of the week, and (b) the minimum number of days that defines the first week of the year or first week of month.

First, for comparison, get the day-of-week number using the standard ISO 8601 definition embodied in the IsoFields class.

// Using standard IsoFields.
LocalDate localDate = LocalDate.of ( 2016 , 2 , 3 ); // Feb 3 2016 = Wednesday
DayOfWeek dow = DayOfWeek.from ( localDate );
int ordinalNumberDayOfWeek = dow.getValue ();

Dump to console.

System.out.println ( "localDate: " + localDate + " | dow: " + dow + " | ordinalNumberDayOfWeek: " + ordinalNumberDayOfWeek );

localDate: 2016-02-03 | dow: WEDNESDAY | ordinalNumberDayOfWeek: 3

Now switch to defining our own WeekFields object, and again ask for the day-of-week number. Above we saw 3 because Feb 3 2016 is a Wednesday, so Monday-Tuesday-Wednesday renders a three. Below we see 4 because of Sunday-Monday-Tuesday-Wednesday.

// Define our own WeekFields to use in place of IsoFields.
WeekFields weekFields_SUNDAY_1 = WeekFields.of ( DayOfWeek.SUNDAY , 1 );
int ordinalNumberDayOfWeek_SundayBasedWeek = localDate.get ( weekFields_SUNDAY_1.dayOfWeek () );

Dump to console.

System.out.println ( "ordinalNumberDayOfWeek_SundayBasedWeek: " + ordinalNumberDayOfWeek_SundayBasedWeek );

ordinalNumberDayOfWeek_SundayBasedWeek: 4

(example based on this Answer by JodaStephen)


See similar Question, java get week of year for given a date.


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.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

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. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

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