Search code examples
javadatedate-formatjava-time

How to count Sundays between specific two dates in Java


I am struggling to count the number of Sundays on the 1st of the months. like input 1 (test case) 1900 1 1 1902 1 1(year, month, day) the output should be 4. Start date is included.

EXPLANATION:

1 April 1900
1 July 1900
1 September 1901
1 December 1901

However, when I tried THIS:

6 4699 12 12 4710 1 1 1988 3 25 1989 7 13 1924 6 6 1925 6 16 1000000000000 2 2 1000000001000 3 2 1925 6 16 1924 6 6 1905 1 1 1905 1 1

OUTPUT SHOULD BE: 18 2 2 1720 0 1

My CODE OUTPUT IS: 18 2 2 **1714** 0 1

In the test input 6 means 6 test cases. 4699 years 12 month, 12 days, so Dec 12, 4699; 4710 end date and so on.

Could you help me to solve this problem?

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Calendar;

public class nineteen {
    
    public static void main(String[] args) throws ParseException {
        SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
        Scanner sc = new Scanner(System.in);
        int loop = sc.nextInt();
        for (int i = 0; i < loop; i++) {
            long year = sc.nextLong(), month = sc.nextLong(), day = sc.nextLong(), yearto = sc.nextLong(),
                    monthto = sc.nextLong(), dayto = sc.nextLong();
            String day1 = String.valueOf(day);
            String month1 = String.valueOf(month);
            String year1 = String.valueOf(year);
            String dayt = String.valueOf(dayto);
            String montht = String.valueOf(monthto);
            String yeart = String.valueOf(yearto);
            String input_date = month1 + "/" + day1 + "/" + year1; // month day year
            String out_date = montht + "/" + dayt + "/" + yeart; // month day year
            long count = 0;

            Date d1 = formatter.parse(input_date);
            Date d2 = formatter.parse(out_date);
            count = saturdayscount(d1, d2);

            // TODO Auto-generated method stub

        }
        sc.close();
    }

    public static long saturdayscount(Date d1, Date d2) {
        Calendar c1 = Calendar.getInstance();
        c1.setTime(d1);

        Calendar c2 = Calendar.getInstance();
        c2.setTime(d2);

        long sundays = 0;

        while (!c1.after(c2)) {

            if (c1.get(Calendar.DAY_OF_MONTH) != 1) {
                c1.add(Calendar.MONTH, 1);
                c1.set(Calendar.DAY_OF_MONTH, 1);

            }

            if (c1.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {

                sundays++;
            }

            c1.add(Calendar.MONTH, 1);
            c1.set(Calendar.DAY_OF_MONTH, 1);
        }

        System.out.println(sundays);
        return sundays;
    }

}

Solution

  • Solution: how to handle out of range dates

    As I said in a comment already, your problem is that 1000000000000 (year 1 000 000 000 000, year one trillion or in classical English year one billion) is out of range for Java’s date libraries. This in combination with the poorly designed and long outdated Date and SimpleDateFormat classes not giving you any notification of the error and just tacitly giving you incorrect data. The answer by Arvind Kumar Avinash demonstrates that java.time, the modern Java date and time API, does notify you of the error. The exact ranges are in the answer by Lino. If you need to handle such years, here’s how.

    Since the standard library doesn’t do the job for us, we will need to do at least some of the work ourselves, “by hand” so to speak. You may of course write your own date code from scratch, but no one should want to do that. Instead observe:

    • Leap years come in a 400 years cycle.
    • January 1, 1900 was a Monday. 400 years later January 1, 2300 will also be a Monday. This means that the days of the week follow the same 400 years cycle.

    So to handle years after year 2300, first calculate the number of Sundays on the first of a month in a full 400 years cycle. java.time, the modern Java date and time API, can do this, as shown in other answers. Now subtract a whole multiple of 400 from the start year to get a year between 1900 and 2300. Count Sundays from this modified start date until January 1, 2300. Similarly subtract a multiple of 400 from the end year. Then count Sundays from 1900. Add the two numbers and adjust for how many cycles at 400 years you subtracted from each of start and end years.

    Remember to use long or BigInteger for years since an int cannot hold such large numbers either.

    I have assumed that years are always 1900 or later, as I believe was also the premise in the original Project Euler challenge (link below). When going back in time, calendar systems tend to disagree, so whether a given Sunday falls on the 1st of a month is no longer well-defined. I am leaving that out of consideration.

    Link: Project Euler.net Counting Sundays Problem 19