5

I have small code such as below. I expected that the result should be 7, but it printed 6. If I uncomment the line tmp.get(Calendar.MONTH), it runs OK (prints 7).

Please let me know the reason. I'm using JDK 1.7.0_25 in MacOS.

public static void main(String[] args) {
    Calendar tmp = Calendar.getInstance();
    tmp.set(Calendar.DAY_OF_MONTH, 4);
    tmp.set(Calendar.MONTH, Calendar.AUGUST);
    //tmp.get(Calendar.MONTH);
    tmp.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    System.out.println(tmp.get(Calendar.MONTH));
}

Screenshot:
Comment code: http://gyazo.com/4c099b1b2b90d72d1954b98b134e4ac3
Uncomment code: http://gyazo.com/fe368745da168646140ca9f3a60d2021

serv-inc
  • 35,772
  • 9
  • 166
  • 188
nhthai
  • 198
  • 2
  • 10
  • have a look at http://stackoverflow.com/questions/6722542/java-calendar-date-is-unpredictable-after-setting-day-of-week – serv-inc Jul 04 '15 at 11:21

5 Answers5

3

Because month index starts with index 0. add +1 while get month. it is c based structure copied into java. It has indexes 0 to 11.

And i think day of month is incorrect. comment that and run it it shows correctly.(tmp.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);)

    tmp.set(Calendar.DAY_OF_MONTH, 4);
    tmp.set(Calendar.MONTH, Calendar.AUGUST);
    //tmp.get(Calendar.MONTH);
    //tmp.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    System.out.println(tmp.get(Calendar.MONTH));

By default it takes year as 2015 and August 4 is tuesday not monday

Bruce
  • 8,609
  • 8
  • 54
  • 83
  • But the August is 8, after minus 1, we should have 7. Right? – nhthai Jul 04 '15 at 10:18
  • I've already known it. So if I change the date of week to monday, it will be moved to the last monday, so it should be Monday August 03. And the last result is 7. – nhthai Jul 04 '15 at 10:26
  • it will override the month set by 2 line of code. have a look on source code. – Bruce Jul 04 '15 at 10:35
2

I tried to run your code and it prints 7 every time (even tried to uncomment that line you mention). Which seems correct to me.

EDIT The problem is explained in detail Java Calendar - Date is unpredictable after setting day_of_week

I am glad that with Java 8 came new API for working with date and time.

EDIT2

My understanding of what happened:

Only sensible combinations are

YEAR + MONTH + DATE (let's call it A)

or

YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK (let's call it B)

And the Calendar has its inner state of date in which he thinks he is. So basically before you set

DAY_OF_WEEK

you were working with combination A but after it you were working with combination B and this line

tmp.set(Calendar.DAY_OF_MONTH, 4);

was ignored. Thus it took Monday in the first week of August (2015-07-27). But when you called

tmp.get(Calendar.MONTH);

you "materialized" the date according to combination A (so to 2015-08-04) and the

DAY_OF_WEEK

was set "correctly" starting from 2015-08-04.

Anyway could you try that with JDK 8?

Community
  • 1
  • 1
jakub.petr
  • 2,951
  • 2
  • 23
  • 34
  • Thanks! I'm thinking about JDK or OS version. That's the reason I share my OS and JDK in question. – nhthai Jul 04 '15 at 10:27
  • Could you add System.out.println(tmp.get(Calendar.MONTH) + ": " + tmp.getTime()); to your code? It would be interesting to see what is your final date then. – jakub.petr Jul 04 '15 at 10:29
  • Result with comment the get function: http://gyazo.com/4c099b1b2b90d72d1954b98b134e4ac3 (6 --- Mon Jul 27 17:33:12 ICT 2015 ) And uncomment it: http://gyazo.com/fe368745da168646140ca9f3a60d2021 (7 --- Mon Aug 03 17:31:23 ICT 2015 ) – nhthai Jul 04 '15 at 10:32
1

When you set DAY_OF_WEEK = MONDAY, Calendar returns back to last Monday and it is 27th of Jul, you can check it with System.out.println(tmp.get(Calendar.DAY_OF_MONTH));

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0

Avoid pre-Java-8 Date and Calendar

The existing Java date and time classes are poor, mutable, and have unpredictable performance.

This applies somehow equally to Calendar, which has some of the same problems. Weaknesses of Calendar (german link) are

  • not really a calendar, but date + time
  • mutable
  • January is 0th month, not 1st
  • unintuitive API: you have to use get(Calendar.HOUR) instead of getHour
  • ...

if you are using Java <8, use Joda-Time

In the comments to java-calendar-date-is-unpredictable-after-setting-day-of-week, Joda-Time is recommended as an alternative by @JonSkeet, as it is by those folks of the JDK Enhancement Proposal. Your code could look like

import org.joda.time.MutableDateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class Test2 {
    public static void main(String[] args) {
    MutableDateTime tmp = new MutableDateTime();
    tmp.setDayOfMonth(4);
    tmp.setMonthOfYear(8);
    tmp.setDayOfWeek(1);

    DateTimeFormatter fmt = DateTimeFormat.fullDate();
    System.out.println(fmt.print(tmp));
    }
}

Immutable

There is also the immutable DateTime class, which you will want to use instead. (immutability adds several positive effects, in Java 8 it is the default)

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class Test {
    public static void main(String[] args) {
        DateTimeFormatter fmt = DateTimeFormat.fullDate();

        DateTime tmp = new DateTime().withDayOfMonth(4).withMonthOfYear(8);
        System.out.println(fmt.print(tmp));

        tmp = tmp.withDayOfWeek(1);
        System.out.println(fmt.print(tmp));
    }
}

If on Java-8,

the java.time API is based on Joda-Time. Use

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class Test {
    public static void main(String[] args) {
        DateTimeFormatter fmt = DateTimeFormatter.RFC_1123_DATE_TIME;

        LocalDateTime tmp
            = LocalDateTime.now().withDayOfMonth(4).withMonthOfYear(8);
        System.out.println(fmt.format(tmp));

        tmp = tmp.withDayOfWeek(1);
        System.out.println(fmt.format(tmp));
    }
}

(I have not tested the Java-8 version)

Community
  • 1
  • 1
serv-inc
  • 35,772
  • 9
  • 166
  • 188
0

When you set the day of week, Calendar has no way to know what you expect. If you expect to get the date of another day of the same week, you should set the week of year too to indicate which week you expect.

BladeCoder
  • 12,779
  • 3
  • 59
  • 51