Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I am posting this code up for review and debugging. This source code is for Java, and is meant to give you the exact day of the week from an entered date.

Review

  1. This program seems to have 2 case statements. Would it have made sense to use an enum variable to eliminate the second case statement?
  2. How about restructuring my entire program to include one super class and a sub class?
  3. Are these approach a good idea to shorten my code, or is my original code the best approach to my program's purpose?

Debugging

Please feel free to test this program out, and reply with any incorrect output given from this code. I have tested this program with various dates and have gotten the correct output. However, it is always a good idea to have more eyes test this code out.

Program Purpose:

Enter any date from the 1800 to the present day, and this program will display the day of the week from the date entered.

Example:

If a user entered "July 2 , 1985". This program will return "Tuesday", which was the day of the week that on "July 2, 1985".

// Import Libraries
import javax.swing.*;
import java.util.*;
import java.io.*;


// This is my program.
public class DateCalc
{
    public static void main (String[] args)
    {
        String month;
        String day;
        String inputYear;
            Scanner  keyboard = new Scanner(System.in);    

                // receiving input for my age variable
                System.out.print( " \n \n Please Enter The Month Of The Date :");
                month = keyboard.nextLine();
                // receiving input for my weight variable
                System.out.print( " \n Please Enter The Day Of The Date : ");
                day = keyboard.nextLine();
                // receiving input for my height variable
                System.out.print( " \n Please Enter The Year OF The Date : ");
                inputYear = keyboard.nextLine();
                String stringYear = ""+ inputYear.charAt(inputYear.length()-2) + inputYear.charAt(inputYear.length()-1);
                int year = Integer.parseInt(stringYear);
                int intDay = Integer.parseInt(day);

        switch(month.toLowerCase()) 
        {  

            case "january" :
            int janKey = 1;
            results (day , inputYear, month, year, intDay, janKey);
            break;


            case "february":  
            int febKey = 4;
            results (day , inputYear, month, year, intDay, febKey);
            break;  


            case "march":  
            int marKey = 4;
            results (day , inputYear, month, year, intDay, marKey);
            break;


            case "april":  
            int aprKey = 0;
            results (day , inputYear, month, year, intDay, aprKey);
            break;

            case "may":  
            int maykey = 2;
            results (day , inputYear, month, year, intDay, maykey);
            break;

            case "june":  
            int junKey = 5;
            results (day , inputYear, month, year, intDay, junKey);
            break;

            case "july":  
            int julKey = 0; 
            results (day , inputYear, month, year, intDay, julKey);
            break;

            case "august":  
            int augKey = 3; 
            results (day , inputYear, month, year, intDay, augKey);
            break;

            case "september":  
            int septKey = 6; 
            results (day , inputYear, month, year, intDay, septKey);
            break;

            case "october":  
            int octKey = 1; 
            results (day , inputYear, month, year, intDay, octKey);
            break;

            case "november":  
            int novKey = 4;
            results (day , inputYear, month, year, intDay, novKey);
            break;

            case "december":  
            int decKey = 4; 
            results (day , inputYear, month, year, intDay, decKey);
            break;

            //  IN MY DEFUALT CASE " inputValidation " WILL BE EXECUTED
            default:
            JOptionPane.showMessageDialog(null," Invalid Entry Please Try Again " );

        }
}

public static void results ( String day , String inputYear, String month, int year, int intDay, int key )
{
    int quarter = year / 4;
    int sum = year + quarter + intDay + key;

            System.out.println(" \n\n\n\n\n\n\n\n\n\n\n\n");
            System.out.println("*********************************************************************** ");
            System.out.println("***********************    Result    ********************************** ");
            System.out.println("*********************************************************************** ");
            System.out.println( " \n\n\t\t Date Entered Was : " );
            System.out.println(" \n \t \t   " + month + "  "+ day + " , " + inputYear );
            System.out.println( " \n\n Last Two Digits Of The Year Were : ........ " + year);
            System.out.println( " \n One Quarter Of Last Two Digits : ........ " + quarter);
            System.out.println( " \n The Given Day Of The Month Entered : ........ " + day);
            System.out.println( " \n The Index Key Of This Month : ........ " + key);
            System.out.println( " \n The Sum Of All The Numbers Above Is : ........ " + sum);
            dayLookUp(sum);
            String weekDay = dayLookUp(sum);
            System.out.println( " \n \n \t The Day Of The Week Was : ........ " + weekDay);
}

public static String dayLookUp ( int sum )
{
    String weekDay;
    String error = " \n \n Please Check Your Dates And Try Again " ;
    int day = sum % 7;

    switch(day) 
        {  

            case 1 :
            weekDay = " Sunday ";
            return weekDay;

            case 2:  
            weekDay = " Monday ";
            return weekDay;

            case 3:  
            weekDay = " Tuesday ";
            return weekDay;

            case 4:  
            weekDay = " Wednesday ";
            return weekDay;

            case 5:  
            weekDay = " Thursday ";
            return weekDay;

            case 6:  
            weekDay = " Friday ";
            return weekDay;

            case 7:  
            weekDay = " Saturday "; 
            return weekDay;

            //  IN MY DEFUALT CASE " inputValidation " WILL BE EXECUTED
            default:
            JOptionPane.showMessageDialog(null," Invalid Entry Please Try Again " );
            return error;
        }
    }
}
share|improve this question
1  
What good do you think it would do to introduce inheritance? –  200_success May 5 at 9:45

2 Answers 2

Formatting

Your intentation is a bit off. Please improve that. Use your IDE's automatic indentation keyboard shortcut for an easy fix (Ctrl + I in Eclipse).

In Java, braces go on the same line, for example

public class DateCalc

{

becomes

public class DateCalc {

Your questions

This program seems to have two case statements. Would it have made sense to use an enum variable to eliminate the second case statement?

Yes. And not only the second. The first as well.

How about restructuring my entire program to include one super class and a sub class?

I see absolutely no reason whatsoever why you'd want to include a superclass and a subclass in this program. The program is simple enough that there's no need to use polymorphism.

Are these approach a good idea to shorten my code, or is my original code the best approach to my program's purpose?

You need to learn how to use the data structures and types that Java provides.

Cleaning up

results(day, inputYear, month, year, intDay, janKey);

You're calling one variant or another of results on all methods. The only variance is in the janKey variable and value that is used.

Months

Here's an example that is using HashMap for this lookup:

Map<String, Integer> monthMap = new HashMap<String, Integer>();
monthMap.put("january" , 1);
monthMap.put("february", 4);
monthMap.put("march"   , 4);
int key = monthMap.get(month.toLowerCase());
results(day, inputYear, month, year, intDay, key);

Of course it'd be better to use an enum.

enum Month {
    JANUARY(1), FEBRUARY(4), MARCH(4);

    public final int key;

    private Month(int key) {
        this.key = key;
    }
}

int key = Month.valueOf(month.toUpperCase()).key;

Weekdays

weekDay = " Wednesday ";
return weekDay;

Get rid of that temporary variable and return directly!

Or, again, even better: Use an enum!!

enum Weekday {
    Sunday, Monday, Tuesday;
}

return Weekday.values()[day - 1];

Input

You seem to only be accepting dates on the 1900's. This is bad. At least provide a decent error message for when a date is outside the range accepted by your program.

I'd like to see more dates supported. At first I actually tried some other dates and discovered that it was incorrect result, then I found out why.

String stringYear = ""+ inputYear.charAt(inputYear.length()-2) + inputYear.charAt(inputYear.length()-1);

I don't like that line at all. First of all, it could be better expressed as

String stringYear = inputYear.substring(inputYear.length() - 2);

secondly, you're asking the user to input more information than what you use. Instead, ask for less input from the user.

I would however, like to see that you instead added support for the following dates:

  • April 22, 2000 was a saturday.
  • September 4, 2012 was a tuesday.
  • May 4, 2014 (today) is a sunday.
  • March 22, year -5 was a friday. (If you extrapolate the Gregorian calendar that far)

Algorithm

Your algorithm seems to be based on a restricted variant of The Doomsday Rule. As is explained on Wikipedia, you could add support for any century. No need to be limited to the 1900's.

Java 8

If possible, use Java 8! Java 8 provides the java.time package which makes it very easy to look-up a day of week:

System.out.println(Year.of(1985).atMonth(Month.JULY).atDay(2).getDayOfWeek());

Outputs:

TUESDAY
share|improve this answer
1  
If Java 8 is not an option, JodaTime is the precursor and provides a nice API. –  David Harkness May 5 at 2:09

User experience bugs

  • The UI is entirely console-based — except that errors are reported in a Swing message dialog. That's bizarre.

  • The user has no way of knowing that the program only accepts fully spelled out month names, not numbers or abbreviations.

  • The blank lines in the output result in excessive vertical spacing, in my opinion.

Algorithm bugs

  • Any Saturday will result in an error, since int day = sum % 7 produces results in the range 0 to 6. Therefore, case 7 will never match, and case 0 is never handled.

    $ java DateCalc
    
    
     Please Enter The Month Of The Date :July
    
     Please Enter The Day Of The Date : 6
    
     Please Enter The Year OF The Date : 1985
    
    
    
    
    
    
    
    
    
    
    
    
    
    *********************************************************************** 
    ***********************    Result    ********************************** 
    *********************************************************************** 
    
    
             Date Entered Was : 
    
               July  6 , 1985
    
    
     Last Two Digits Of The Year Were : ........ 85
    
     One Quarter Of Last Two Digits : ........ 21
    
     The Given Day Of The Month Entered : ........ 6
    
     The Index Key Of This Month : ........ 0
    
     The Sum Of All The Numbers Above Is : ........ 112
    
    
         The Day Of The Week Was : ........  
    
     Please Check Your Dates And Try Again
    
  • You have a Y2K bug. Since you discard the first two digits of the year, calculations all seem to assume the 20th century.

    $ java DateCalc
    
    
     Please Enter The Month Of The Date :May
    
     Please Enter The Day Of The Date : 5
    
     Please Enter The Year OF The Date : 2014
    
    
    
    
    
    
    
    
    
    
    
    
    
    ***********************************************************************
    ***********************    Result    **********************************
    ***********************************************************************
    
    
                     Date Entered Was :
    
                       May  5 , 2014
    
    
     Last Two Digits Of The Year Were : ........ 14
    
     One Quarter Of Last Two Digits : ........ 3
    
     The Given Day Of The Month Entered : ........ 5
    
     The Index Key Of This Month : ........ 2
    
     The Sum Of All The Numbers Above Is : ........ 24
    
    
             The Day Of The Week Was : ........  Tuesday
    

Code structure issues

You have three functions: main(), results(), and dayLookup().

  • main() is too long. You can't tell at a glance what the outline of the program is. Most of it has to do with prompting for a date, so that should be split into a separate function.

  • dayLookup(), being a lookup, should be replace by an array lookup.

  • The method signature for results() is awkward.

Code hygiene issues

  • import java.io.* is superfluous. The fact that it's a wildcard import makes it worse than an extra single-class import.

  • You have some mismatched comments regarding the use of Scanner.

  • You opened the Scanner without closing it after use.

  • Your indentation is inconsistent.

Proposed implementation

Without changing the core of the algorithm, this is how I would reorganize the code.

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

public class DateCalc
{
    private static String[] MONTH_NAMES = new String[] {
        "January", "February", "March", "April",
        "May", "June", "July", "August",
        "September", "October", "November", "December"
    };
    private static int[] MONTH_KEYS = new int[] {
        1, 4, 4, 0,
        2, 5, 0, 3,
        6, 1, 4, 4
    };
    private static String[] DAYS_OF_WEEK = new String[] {
        "Saturday",
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday"
    };

    /**
     * Prompts for a date.
     *
     * @return A three-element array, consisting of the year, month, and day of
     *         month.  The month is 0-based, i.e. 0 represents January.
     */
    public static int[] promptDate(Scanner in) throws ParseException {
        System.out.print( " Please Enter The Month (e.g. \"January\") : ");
        String month = in.nextLine();
        System.out.print( " Please Enter The Day Of The Date : ");
        String day = in.nextLine();
        System.out.print( " Please Enter The Year Of The Date : ");
        String year = in.nextLine();

        int[] result = new int[3];
        try {
            int yyyy = result[0] = Integer.parseInt(year);
            int dd   = result[2] = Integer.parseInt(day);
            for (int i = 0; i < MONTH_NAMES.length; i++) {
                if (MONTH_NAMES[i].equalsIgnoreCase(month)) {
                    int mm = result[1] = i;
                    return result;
                }
            }
            throw new ParseException("Invalid month " + month, 0);
        } catch (NumberFormatException e) {
            throw new ParseException(e.getMessage(), 0);
        }
    }

    public static String results(int[] ymd) {
        int yyyy = ymd[0];
        int mm = ymd[1];
        int dd = ymd[2];

        int yy = ymd[0] % 100;
        int quarter = yy / 4;
        int monthKey = MONTH_KEYS[mm];
        int sum = yy + quarter + dd + monthKey;

        return String.format(
            "***********************************************************************\n" +
            "***********************    Result    **********************************\n" +
            "***********************************************************************\n" +
            "\n" +
            "\t\t Date Entered Was :\n" +
            "\t \t   %s %s, %s\n" +
            "\n" +
            " Last Two Digits Of The Year Were : ........ %s\n" +
            " One Quarter Of Last Two Digits : ........ %s\n" +
            " The Given Day Of The Month Entered : ........ %s\n" +
            " The Index Key Of This Month : ........ %s\n" +
            " The Sum Of All The Numbers Above Is : ........ %s\n" +
            "\n" +
            " The Day Of The Week Was : ........ %s",
            MONTH_NAMES[mm], dd, yyyy,
            yy, quarter, dd, monthKey, sum,
            DAYS_OF_WEEK[sum % 7]
        );
    }

    public static void main(String[] args) {
        int[] ymd = null;
        try (Scanner in = new Scanner(System.in)) {
            do {
                try {
                    ymd = promptDate(in);
                } catch (ParseException badDate) {
                    System.err.println(" Invalid Entry Please Try Again " );
                }
            } while (ymd == null);
        }

        System.out.println("\n");
        System.out.println(results(ymd));
    }

}

Using Java 7 libraries

-handling code is always complicated. Unless you are deliberately , you should use existing libraries.

@Simon has given a solution using Java 8. If you are not ready to use Java 8, then the following function would work.

import java.text.*;
import java.util.Date;
import java.util.Locale;

/**
 * Computes the day of the week for a given date.
 *
 * @param ymd A date of the form "January 1, 2014"
 * @return The day of week, e.g. "Saturday"
 */
public static String dayOfWeek(String mmmmdyyyy) throws ParseException {
    DateFormat inFmt = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US);
    Date d = inFmt.parse(mmmmdyyyy);

    StringBuffer sb = new StringBuffer();
    DateFormat outFmt = DateFormat.getDateInstance(DateFormat.FULL, Locale.US);
    FieldPosition dowField = new FieldPosition(DateFormat.DAY_OF_WEEK_FIELD);
    outFmt.format(d, sb, dowField);
    return sb.substring(dowField.getBeginIndex(), dowField.getEndIndex());
}
share|improve this answer
    
Closing the scanner closes System.in which means that the second time promptDate is called you get a NoSuchElementException. –  fgb May 5 at 11:24
    
@fgb You're right: closing the scanner also closes System.in. Rev 2 should address that. –  200_success May 5 at 17:13
    
100% behind use of static arrays over case statements -- just all positive -- easier to read -- easier to maintain -- and faster. –  Hogan May 5 at 23:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.