4

i am a programming enthusiast currently studying for Business Informatics. We have started programming with Java for two months now and i found this website to be of tremendous help in most of the cases i had to write some code for my assignments.

There is however, this assignment for which i have to implement a class that asks a user for a calendar date, validates the date and afterwards calculates and prints the weekday of that date. The program cannot accept dates which do not exist.

The user enters the date in the YYYYMMDD format.

Any impossible date is rejected:

– dates before Oct. 15th 1582 or after Dec, 31st, 2199

– impossible month (<1 or >12)

– impossible day (e.g. any day>31, a day>30 for some months, a day>28 in February of a non-leap year, etc).

We are asked to use the formula derived by Gauss:

A = d + [2.6 x m − 0.2] + y + [y/4]+ [c/4] - (2 x c)
W = A % 7

where

  • [x] is the Gauss-operator: [x] biggest integer x'<= x

  • d represents the day

  • y represents the last two digits of the year

  • c represents the first two digits of the year (actually all but the last two; c stands for century)

  • m represents the month

  • w is weekday

We are also asked to implement a few functions to achieve this task. See my code below:

public class Weekdays {

public static void main(String[] args) {


        TextIO.putln("enter date (yyyymmdd)");
        int date = TextIO.getInt();
        int inDay = date % 100, inMonth = date % 10000 / 100, inYear = date / 10000;
        if(validate(inYear, inMonth, inDay)){
        int W = weekday(inDay, inMonth, inYear);
        String weekday = dayName(W);
        TextIO.putf("%02d.%02d.%4d was/is or will be a %s", date % 100, date % 10000 / 100,
        date / 10000, weekday);
        }else {
        TextIO.putf("invalid date (%d)\n", date);
        }
        }

public static boolean validate (int year) {

    if (year < 1582 || year > 2199) {

        return false;
    }
    else {
        return true;
    }
}

public static boolean validate (int year, int month) {


    if ((year < 1582 || year > 2199)) {

        return false;
    }

    else if (month < 1 || month > 12) {
        return false;
    }

    else if (year == 1582 && month < 10) {

        return false;
    }
    else {
        return true;
    }
}

public static boolean isLeap (int inYear) {
    return (((inYear % 4 == 0) && (inYear % 400 == 0 || inYear % 100 != 0) ));
}

public static int nDays (int month, int year) {

    if ((((year % 4 == 0) && (year % 400 == 0 || year % 100 != 0) ))) {

        if (month == 2) {
            return 29;
        }
        else if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) {
            return 30;
        }
        else {
            return 31;
        }

    }

        else if (year == 1582 && month == 10) {
            return 16;
    }
        else {

            if (month == 2) {
            return 28;
            }
            else if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) {
            return 30;
            }
            else {
            return 31;
        }

    }

}

public static boolean validate (int year, int month, int day) {

    if ((year == 1582 && month == 10) && day < 16) {
        return false;
    }
    else if ((year == 1582 && month == 10) && day <= 31) {

    }
    return (validate(year,month) && day > 0 && day <= nDays(month,year));





}

public static int weekday (int inDay, int inMonth, int inYear) {

    int  month, year, day,c;
    year = inYear;
    day = inDay;

    if (inMonth < 3) {
        year--;
        inMonth = inMonth +10;
    }
    else {
        inMonth = inMonth -2;
    }

    month = inMonth;


    c = year/100;
    year = year%100;

    int A = (int) (day+((2.6*month)-0.2)+year+(year/4)+(c/4)-(2*c));

    int x = A % 7;

    if (x < 0) {
        x+=7;
    }

    return x;

}

public static String dayName (int W) {

    switch (W) {

    case 0: return "Sunday";

    case 1: return "Monday";

    case 2: return "Tuesday";

    case 3: return "Wednesday";

    case 4: return "Thursday";

    case 5: return "Friday";

    case 6: return "Saturday";

    default: return "invalid date (" +W+ ")";
    }
    }


}

I have a problem when i am testing two dates, 21010101 and 19190303 respectively. My program outputs wrong weekday's for these two dates. As much as i tried i simply cannot find a way around to it. I know my code is not the best but i am doing what i can as a beginner. Any help would be appreciated. Thank you!

Mick Mnemonic
  • 7,808
  • 2
  • 26
  • 30
ibu
  • 150
  • 3
  • 17
  • What day are you getting, and what day do you expect? – Elliott Frisch Oct 11 '15 at 00:38
  • For 19190303 Monday is expected, i get Tuesday. For 21010101 Saturday is expected, i get Sunday. – ibu Oct 11 '15 at 00:40
  • Why, does this piece of spaghetti give any correct results for any other dates? Time is something very hard to get right, and libraries that do the kind of stuff that you are trying to do above have many hundreds of lines of code there where you have a few dozen. Why don't you play with something easier, like graphics, and leave time to the time libraries? – Mike Nakis Oct 11 '15 at 00:48
  • 2
    I edited the post to include a link to the wikipedia article about [Gauss' algorithm for determining the day of week](https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Disparate_variation), which I assume explains what you're attempting to implement in the `weekday` method. – Mick Mnemonic Oct 11 '15 at 00:53
  • I haven't got to the point to be able to use libraries effectively, because like i mentioned on my description, i have been learning Java for only two months. This is an assignment which we have to do, and i was wondering if i could get some help here. Thanks @Mike Nakis – ibu Oct 11 '15 at 00:54
  • 1
    Prompt for a date? Easy. Validate the date? Easy. But find the day of the week by yourself? Are you sure that the assignment actually wants you to do that instead of using the standard library functions for obtaining the day of the week? To me it looks like an assignment to prove that you can cook Peking Duck which requires that you begin by finding a shotgun and hunting down the duck. – Mike Nakis Oct 11 '15 at 01:04

2 Answers2

3

You seem to have a rounding error where you calculate the term that corresponds to the month value in A:

int A = (int) (day+((2.6*month)-0.2)+year+(year/4)+(c/4)-(2*c));

Here, the result of (2.6*month) will be cast ("floored") to an int before subtracting 0.2, setting the weekday off by one with some month values. You should extract out this term and use Math.floor() ("Gauss operator"; denoted by square brackets in your formula) for calculating the result instead:

int monthTerm = (int) Math.floor((2.6 * month) - 0.2);
int A = day + monthTerm + year + (year / 4) + (c / 4) - (2 * c);

The results of (year / 4) and (c / 4) will be implicitly "floored" / truncated correctly because both operands are ints.

Mick Mnemonic
  • 7,808
  • 2
  • 26
  • 30
2

Use Math.round(float). Like,

int A = Math.round((day + ((2.6f * month) - 0.2f) + year
        + (year / 4) + (c / 4) - (2 * c)));
int x = A % 7;

And I get (the requested)

01.01.2101 was/is or will be a Saturday

and

03.03.1919 was/is or will be a Monday
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249