Matt Voda
Matt Voda

Reputation: 131

Finding every first Sunday of the month between 1900 and a user-input year

This is homework.

I am trying to find every occurrence of a Sunday landing on the first of a month between Jan 1 1900 (which we are assuming was a Monday) and Dec 31 of a year that the user inputs. The calendar extension is off-limits.

I am returning dates in the correct format, but they do not match up with the example code our instructor provided.
In the given example, an input of 1902 should return:
1 Apr 1900
1 Jul 1900
1 Sep 1901
1 Dec 1901
1 Jun 1902

For 1902, my code returns:
1 Mar 1900
1 Jan 1901
1 Apr 1901
1 May 1901
1 Feb 1902
1 Jun 1902
1 Jul 1902

import java.util.Scanner;


public class Sundays {

public static void main(String[] args) {
    Scanner reader = new Scanner(System.in);

    System.out.print("Enter the ending year: ");
    int userInputYear = reader.nextInt();

    int[] orderedLengthOfMonthsArray = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    String[] orderedNamesOfMonthsArray = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
    int month = 0;
    int dayOfWeek = 1; // initialized to MONDAY Jan 1, 1900 -- Sunday would be #7
    int dayOfMonth = 1;


    for (int year = 1900; year <= userInputYear; year++) {

        for (month = 0; month < orderedLengthOfMonthsArray.length; month++) {


            for (dayOfMonth = 1; dayOfMonth <= orderedLengthOfMonthsArray[month]; dayOfMonth++) {

                dayOfWeek++;

                if (dayOfMonth == 1 && dayOfWeek == 7) {
                    System.out.println(dayOfMonth + " " + orderedNamesOfMonthsArray[month] + " " + year);
                }

                if (dayOfWeek == 8) {
                    dayOfWeek = 1;
                }                   
            }
        }
    }
}  
}

Upvotes: 1

Views: 1297

Answers (4)

Anthony Accioly
Anthony Accioly

Reputation: 22471

Just for fun, while you have explicitly mentioned not to use Calendar, here is how we could do it:

public static List<Date> mondaysFirst(int firstYear, int lastYear) {
    final List<Date> dates = new ArrayList<>();
    final Calendar c1 = Calendar.getInstance(Locale.US);
    c1.set(firstYear, 0, 1, 0, 0, 0);
    final Calendar c2 = Calendar.getInstance(Locale.US);
    c2.set(lastYear, 11, 31, 23, 59, 59);

    while (c1.before(c2)) {
        final int dayOfTheWeek = c1.get(Calendar.DAY_OF_WEEK);
        // is sunday
        if (dayOfTheWeek == 1) {
            dates.add(c1.getTime());    
        }
        c1.add(Calendar.MONTH, 1);
    }

    return dates;
}

And to print the results:

final List<Date> dates = mondaysFirst(1900, 1902);
final SimpleDateFormat sf = new SimpleDateFormat("dd MMM yyyy");
for (Date date: dates) {
    System.out.println(sf.format(date));
}

Working Example.


I'm sure that there is some Joda-Time magic to make this even shorter.

Upvotes: 0

Basil Bourque
Basil Bourque

Reputation: 339332

Someone mentioned Joda-Time magic… So here's my solution using Joda-Time 2.3.

While the question (a homework assignment) forbade the use of added libraries…

  • The comparison may be enlightening.
  • The student should soon learn that the java.util.Date & Calendar classes are notoriously troublesome and should be avoided for real-world work. They are supplanted in Java 8 by the new java.time.* package which is inspired by Joda-Time and defined by JSR 310.

My example code uses LocalDate which should only be used if your are absolutely certain that you don't care about (a) time of day, and (b) time zones. I do not usually recommend this approach as naïve programmers who believe they need neither time nor zone often turn out to be mistaken.

// Start
LocalDate start = new LocalDate( 1900, 1, 1 );

// Stop
// Using "half-open" comparison. We care about December 31 of specified year, but we will test for January 1 of year after.
String input = "1930";
int year = Integer.valueOf( input );
year = ( year + 1 );  // Add one to get to next year, for "half-open" approach.
LocalDate stop = new LocalDate( year, 1, 1 );

// Collect each LocalDate where the first of the month is a Sunday.
java.util.List<LocalDate> localDates = new java.util.ArrayList<LocalDate>();
LocalDate localDate = start;
do {
    if ( localDate.getDayOfWeek() == DateTimeConstants.SUNDAY ) { // Comparing 'int' primitive values.
        localDates.add( localDate ); // Collect this LocalDate instance.
    }
    localDate = localDate.plusMonths( 1 ); // Move on to next month. Joda-Time is smart about various month-ends and leap-year.
} while ( localDate.isBefore( stop ) ); // "Half-Open" means test "<" rather than "<=".

Dump to console…

System.out.println( "The First-Of-The-Month days that are Sundays from " + start + " (inclusive) to " + stop + " (exclusive):" );
System.out.println( localDates );
The First-Of-The-Month days that are Sundays from 1900-01-01 (inclusive) to 1931-01-01 (exclusive):
[1900-04-01, 1900-07-01, 1901-09-01, 1901-12-01, 1902-06-01, 1903-02-01, 1903-03-01, 1903-11-01, 1904-05-01, 1905-01-01, 1905-10-01, 1906-04-01, 1906-07-01, 1907-09-01, 1907-12-01, 1908-03-01, 1908-11-01, 1909-08-01, 1910-05-01, 1911-01-01, 1911-10-01, 1912-09-01, 1912-12-01, 1913-06-01, 1914-02-01, 1914-03-01, 1914-11-01, 1915-08-01, 1916-10-01, 1917-04-01, 1917-07-01, 1918-09-01, 1918-12-01, 1919-06-01, 1920-02-01, 1920-08-01, 1921-05-01, 1922-01-01, 1922-10-01, 1923-04-01, 1923-07-01, 1924-06-01, 1925-02-01, 1925-03-01, 1925-11-01, 1926-08-01, 1927-05-01, 1928-01-01, 1928-04-01, 1928-07-01, 1929-09-01, 1929-12-01, 1930-06-01]

Upvotes: 1

yasen
yasen

Reputation: 1260

Swap the if statement and the increase of dayOfWeek.

        for (dayOfMonth = 1; dayOfMonth <= orderedLengthOfMonthsArray[month]; dayOfMonth++) {
            if (dayOfMonth == 1 && dayOfWeek == 7) {
                System.out.println(dayOfMonth + " " + orderedNamesOfMonthsArray[month] + " " + year);
            }

            dayOfWeek++;

            if (dayOfWeek == 8) {
                dayOfWeek = 1;
            }                   
        }

When you are in the dayOfMonth for loop, you already have the correct day of the week (initially Monday, Jan 1st, 1900), so if you first increase it, then the check afterwards would be incorrect.

Upvotes: 3

exception1
exception1

Reputation: 1249

if (dayOfWeek == 7) {
    dayOfWeek = 1;
}  

So your week has 6 days? I think you should either reset to zero or reset when dayOfWeek is 8.

Upvotes: 1

Related Questions