0

The question is to get day numbers of February of any year. My code is like this:

public static void main(String[] args) {
    System.out.println("2014-02 has " + getDaysOfFeb(2014) + "days");
    System.out.println("2016-02 has " + getDaysOfFeb(2016) + "days");
}

public static int getDaysOfFeb(int year) {
    Calendar c = Calendar.getInstance();
    // set year-01-31
    c.set(year, 0, 31);
    long lastDayofJan = c.getTimeInMillis();

    // set year-03-01
    c.set(year, 2, 1);
    long firstDayOfMar = c.getTimeInMillis();

    int date = (int) ((firstDayOfMar - lastDayofJan) / 1000 / 60 / 60 / 24);
}

I got Jan 31st and Mar 1st, I use the difference of time to calculate the day numbers. But the result is:

2014-02 has 29days
2016-02 has 30days

I don't understand why.

When I do like this:

public static int getDaysOfFeb(int year) {
    Calendar c = Calendar.getInstance();
    // set year-01-31
    c.set(year, 2, 1);
    c.add(Calendar.DATE, -1); // last day of Feb
    int date = c.get(Calendar.DATE);
    return date;
}

The result is right, as follow:

2014-02 has 28days
2016-02 has 29days

Does anyone know what the difference is here?

Jonny Henly
  • 4,023
  • 4
  • 26
  • 43
  • What where the results of subtracting the last day of February from the last day of January? In other words, how many days have elapsed since the last day of January to the first day of March? – Jonny Henly Jul 18 '16 at 20:07
  • 1
    Imagine that there is one day in Feb - so 31st Jan is the 31st day of the year and 1st of March is the 33rd day of the year - the difference is 2 and the result is that there is one day in Feb... So you need to subtract 1 from your calculation. – assylias Jul 18 '16 at 20:11
  • Okay. I got it. (1st Mar) - (31th Jan) = (days of Feb) + 1; Thks – Zhengshuai PENG Jul 18 '16 at 20:16
  • Could also use: [```Month.FEBRUARY.length(Year.isLeap(year));```](https://docs.oracle.com/javase/8/docs/api/java/time/Month.html#length-boolean-) – Jorn Vernee Jul 18 '16 at 20:31

5 Answers5

2

It is exactly how it should be. The difference between March, 1 and January, 31 is one day more than the number of days in February. In general, the difference between the same days in two consecutive months is the number of days in the earliest of these two months. So, the difference between March, 1 and February, 1 is the number of days in February, as well as the difference between March, 10 and February, 10 (and any other day). The difference between April, 1 and March, 1 is always 31 (the number of days in March) and so on.

Ruslan Batdalov
  • 793
  • 1
  • 8
  • 21
0

Not that this is an exact answer. But I wrote a quick Java program a while ago that will generate a calendar for pretty much whatever month/year you want. The example falls directly in line with what you're trying to do. Here is the code running on TutorialsPoint: Calendar in Java

Code:

import java.util.Calendar;

public class calDays {

    /**
     * @param args
     */
    static Calendar today = Calendar.getInstance();
    static int curDay = today.get(Calendar.DAY_OF_MONTH);
    static int curMonth = today.get(Calendar.MONTH);
    static int curYear = today.get(Calendar.YEAR);

    public static void main(String[] args) {

        drawCal(curMonth,curYear);
        drawCal(5,1969);
        drawCal(4,2001);
    }

    public static void drawCal(Integer monthIs, Integer yearIs){
        System.out.println(""+getMonth(monthIs)+" "+yearIs);
        System.out.println("S  M  T  W  T  F  S  ");

        int calDayBox =0;

        Calendar monthtd = Calendar.getInstance();
        monthtd.set(Calendar.DAY_OF_MONTH,1);
        monthtd.set(Calendar.MONTH, monthIs);
        monthtd.set(Calendar.YEAR, yearIs);

        int daysInMonth = monthtd.getActualMaximum(Calendar.DAY_OF_MONTH);

        int allboxes=0;
        //Draw leading days
        int CalDaxBoxVal=1;
        for (int xx=0;xx<monthtd.get(Calendar.DAY_OF_WEEK)-1;xx++){
            System.out.print("_  ");
            calDayBox++;
            allboxes++;
        }

        for (int xx=calDayBox;xx<daysInMonth+calDayBox;xx++){
            System.out.print(""+CalDaxBoxVal+ " ");
            if (CalDaxBoxVal<10) System.out.print(" ");
            CalDaxBoxVal++;
            allboxes++;
            if (allboxes%7==0) System.out.println(); 
        }

        System.out.println();
        System.out.println();



    }

    public static String getMonth(Integer whichMonth){
        String monthsAre[] = new String[12];
        monthsAre[0]="January";
        monthsAre[1]="February";
        monthsAre[2]="March";
        monthsAre[3]="April";
        monthsAre[4]="May";
        monthsAre[5]="June";
        monthsAre[6]="July";
        monthsAre[7]="August";
        monthsAre[8]="September";
        monthsAre[9]="October";
        monthsAre[10]="November";
        monthsAre[11]="December";

        return monthsAre[whichMonth];
    }

}
durbnpoisn
  • 4,666
  • 2
  • 16
  • 30
0

Change your first method to something like this.

 Calendar c = Calendar.getInstance();  
 c.set(year, 1, 1);
 long firstDayOfFeb= c.getTimeInMillis();

 c.set(year, 2, 1);
 long firstDayOfMar = c.getTimeInMillis();

 int date = (int) ((firstDayOfMar - firstDayOfFeb) / 1000 / 60 / 60 / 24);
 return date;

In your calculation you are actually calculating from last day of january to 1 st dat of March, where as you should start from 1 st day of Feb to 1st day of march for correct answer. The problem is with calculation.

Dishant Anand
  • 362
  • 1
  • 14
  • Thanks, to calculate the days of each days, it should be 1st Month - 1st Another Month – Zhengshuai PENG Jul 18 '16 at 20:19
  • you can do it somewhat like this . Calendar c = Calendar.getInstance(); c.set(year, 0, 31); c.add(Calendar.DATE, 1); long lastDayofJan = c.getTimeInMillis(); c.set(year, 2, 1); long firstDayOfMar = c.getTimeInMillis(); int date = (int) ((firstDayOfMar - lastDayofJan) / 1000 / 60 / 60 / 24); return date; – Dishant Anand Jul 18 '16 at 20:25
0

This can be easily answered with simple mathematics.

If you are subtracting 0 from 30, (30 - 0 = ?) you get 30.
If you are subtracting 1 from 30, (30 - 1 = ?) you get 29.

Pretend 0 is February 0th (which is equivalent to January 31st)
Pretend 30 is February 30th (which is equivalent to March 1st on a leap year)

So therefore, March 1st - January 31st must be 30 days.

In order to get the desired number of days, you must subtract 1 from 30, and not 0 from 30.

Pretend 1 is February 1st
Pretend 30 is February 30th (which is equivalent to March 1st on a leap year)

Therefore, you would need to subtract March 1st from February 1st in order to get the correct number of days in February.

Yidna
  • 452
  • 4
  • 12
0

tl;dr

YearMonth.parse( "2014-02" ).lengthOfMonth()

Avoid old date-time classes

The Question and other Answers use troublesome old legacy date-time classes bundled with the earliest versions of Java. Now supplanted by the java.time classes.

YearMonth

Among the java.time classes is YearMonth to represent, well, a year and month.

Note that in java.time the months have sane numbering, 1-12 for January-December (unlike the crazy 0-11 in old date-time classes).

YearMonth ym = YearMonth.parse( "2014-02" );

Or you can make use of the handy Month enum.

YearMonth ym = YearMonth.of( 2014 , Month.FEBRUARY );

Interrogate for the number of days in that month by calling lengthOfMonth.

int lengthOfMonth = ym.lengthOfMonth() ;

You can ask if the year of that year-month is a Leap Year by calling isLeapYear.

boolean isLeapYear = ym.isLeapYear();

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

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

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

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

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.

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