0

I've written this program using Java in Eclipse.
I was able to utilize a formula I found that I explained in the commented out section.
Using the for loop I can iterate through each month of the year, which I feel good about in that code, it seems clean and smooth to me. Maybe I could give the variables full names to make everything more readable but I'm just using the formula in its basic essence :)

Well my problem is it doesn't calculate correctly for years like 2008... Leap Years.
I know that if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) then we have a leap year.

Maybe if the year is a leap year I need to subtract a certain amount of days from a certain month.

Any solutions, or some direction would be great thanks :)

package exercises;

public class E28 {
/*
 * Display the first days of each month
 * Enter the year
 * Enter first day of the year
 * 
 * h = (q + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5j) % 7
 * 
 * h is the day of the week (0: Saturday, 1: Sunday ......)
 * q is the day of the month
 * m is the month (3: March 4: April.... January and Feburary are 13 and 14)
 * j is the century (year / 100)
 * k is the year of the century (year %100)
 * 
 */
public static void main(String[] args) {
    java.util.Scanner input = new java.util.Scanner(System.in);
    System.out.print("Enter the year: ");
    int year = input.nextInt();

    int j = year / 100; // Find century for formula
    int k = year % 100; // Find year of century for formula

    // Loop iterates 12 times. Guess why.
    for (int i = 1, m = i; i <= 12; i++) { // Make m = i. So loop processes formula once for each month
        if (m == 1 || m == 2)              
            m += 12;                       // Formula requires that Jan and Feb are represented as 13 and 14
        else
            m = i;                         // if not jan or feb, then set m to i

        int h = (1 + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5 * j) % 7; // Formula created by a really smart man somewhere
        // I let the control variable i steer the direction of the formual's m value

        String day;
        if (h == 0)
            day = "Saturday";
        else if (h == 1)
            day = "Sunday";
        else if (h == 2)
            day = "Monday";
        else if (h == 3)
            day = "Tuesday";
        else if (h == 4)
            day = "Wednesday";
        else if (h == 5)
            day = "Thursday";
        else 
            day = "Friday";

        switch (m) {
        case 13: 
            System.out.println("January 1, " + year + " is " + day);
            break;
        case 14:
            System.out.println("Feburary 1, " + year + " is " + day);
            break;
        case 3:
            System.out.println("March 1, " + year + " is " + day);
            break;
        case 4:
            System.out.println("April 1, " + year + " is " + day);
            break;
        case 5:
            System.out.println("May 1, " + year + " is " + day);
            break;
        case 6:
            System.out.println("June 1, " + year + " is " + day);
            break;
        case 7:
            System.out.println("July 1, " + year + " is " + day);
            break;
        case 8:
            System.out.println("August 1, " + year + " is " + day);
            break;
        case 9:
            System.out.println("September 1, " + year + " is " + day);
            break;
        case 10:
            System.out.println("October 1, " + year + " is " + day);
            break;
        case 11:
            System.out.println("November 1, " + year + " is " + day);
            break;
        case 12:
            System.out.println("December 1, " + year + " is " + day);
            break;
        }
    }
}
}
xdaimon
  • 98
  • 1
  • 2
  • 9

4 Answers4

7

Do you need to develop your own algorithm? GregorianCalendar class have method:

boolean isLeapYear(int year)

This method returns true if year is a leap year and false otherwise.

Denis.Kipchakbaev
  • 970
  • 15
  • 24
  • The OP's problem isn't figuring out which year is a leap year, but how to calculate a day-of-week when the year is a leap year. – CodesInChaos Oct 12 '12 at 11:11
5

You should use JodaTime for all things to do with dates in Java and it's easy to use.

Using JodaTime you won't have to worry about leap years or anything as it takes care of it all for you. A simple for loop and a DateTime object will give you what you need.

    int year = 2012;

    DateTime dt = new DateTime(year, 01, 01, 00, 00, 00, 00);
    for (int i = 0; i < 12; i++) {
        System.out.println(dt.toString() + " " + dt.property(DateTimeFieldType.dayOfWeek()).getAsText());
        dt = dt.plusMonths(1);
    }

You would obviously replace the year variable with your input, but basically the code works as so:

  • Initialise a DateTime object for the year input starting at 01 January.
  • Print out the current DateTime and the day of the week as a text format
  • Increment the month in the DateTime object by 1.

Outputs:

2012-01-01T00:00:00.000+11:00 Sunday
2012-02-01T00:00:00.000+11:00 Wednesday
2012-03-01T00:00:00.000+11:00 Thursday
. . . 
Deco
  • 3,261
  • 17
  • 25
2

int h = (1 + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5 * j) % 7; // Formula created by a really smart man somewhere

Here's your problem. That formula is Zeller's Congruence, named after Christian Zeller. You aren't using it correctly. The problem is that in this formula, you have to treat January and February as the 13th and 14th month of the previous year. For example, you need to tread February, 2000 as the 14th month of 1999.

Addendum
Your program would have yielded Thursday for February 1, 2000. The correct answer is Tuesday.

As an example, let's use the formula to calculate the day of the week for February 29, 2000. (The algorithm is general; just replace your 1 with the day of the month.)

We're in February, so we have to calculate as if this were the 14th month of 1999. With this, j is 19, k is 99, m is 14. I'll use d=29 rather than 1 in the congruence. With this, h = (d + (26 * (m + 1)) / 10 + k + k/4 + j/4 + 5*j) % 7 = (29 + (26*(14+1))/10 + 99 + 99/4 + 19/4 + 5*19) % 7 = 290 % 7 = 3. Counting from Saturday=0, that's Tuesday.

To verify, a quick and dirty perl script:

#!/usr/bin/perl
# Usage: dayofweek.pl <year number> <month number> <day of month>
# Validation of inputs is an exercise left to the reader.
my ($y, $m, $d) = @ARGV;
use integer; 
my $wd = [qw(Sun Mon Tues Wednes Thurs Fri Satur)]->
         [(index `cal $m $y | tail +3 | grep -E "(^| )$d( |\$)"`, $d) / 3]; 
print "$y/$m/$d -> ${wd}day\n";

Running this against 2000 2 29 yields 2000/2/29 -> Tuesday, as expected.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
0

I have not gone through your code, but for a leap year check you should do this: (Source: Wiki-Leap Year Alg.)

if year modulo 400 is 0 then
   is_leap_year
else if year modulo 100 is 0 then
   not_leap_year
else if year modulo 4 is 0 then
   is_leap_year
else
   not_leap_year

Also see a similar question (and answer) here: stackOverFlow-calc-leap-year

Community
  • 1
  • 1
NoChance
  • 5,632
  • 4
  • 31
  • 45