Hello and thanks in advance for the assistance. I have a program that is supposed to print the current month calendar based on the user inputs of month and year. The program mostly work but i am having issues with formatting and the first day of the month is not starting under the proper date.
Example output:
October 2020
------------------------------
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
October 2020 will begin on a Thursday, but 1 is printed under Mon. October 4th is a Sunday, so that is where the new line should begin.
Please see attached my code. Thanks again
import java.util.*;
public class CalendarMonthDisplay {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); //Scan for user input
System.out.print("Please enter a month between 1 and 12 (e.g. 5): "); //Prompt user to enter month
int m = input.nextInt();
System.out.print("Please enter a full year (e.g. 2018): "); //Prompt user to enter year
int y = input.nextInt();
//Print calendar for the month of the year
if ( m < 1 || m > 12)
System.out.print("Wrong input! Please try again.");
else
printMonthCalendar(m, y);
}
static void printMonthCalendar (int m, int y) { //Display calendar in format above
int startDay = getStartDay(m, y);
int numDaysInMonths = getNumDaysInMonth(m, y);
printMonthHeader(m, y);
printMonthBody(startDay, numDaysInMonths);
}
static void printMonthBody (int startDay, int numDaysInMonths) { //Display the days in the calendar
int i;
for (i = 0; i <= startDay; i++)
System.out.print(" ");
for (i = 1; i <= numDaysInMonths; i++) {
if ( i < 10 )
System.out.print(" " + i );
else
System.out.print(" " + i + " ");
if ((startDay + i) % 7 == 0)
System.out.println();
}
System.out.println();
}
static void printMonthHeader (int m, int y) { //Display the header information
System.out.println("\t" + getMonthName(m) + " " + y);
System.out.println("------------------------------");
System.out.println(" Sun Mon Tue Wed Thu Fri Sat");
}
static String getMonthName (int m) {
String monthName = null;
switch (m) {
case 1: monthName = "January";
break;
case 2: monthName = "February";
break;
case 3: monthName = "March";
break;
case 4: monthName = "April";
break;
case 5: monthName = "May";
break;
case 6: monthName = "June";
break;
case 7: monthName = "July";
break;
case 8: monthName = "August";
break;
case 9: monthName = "September";
break;
case 10: monthName = "October";
break;
case 11: monthName = "November";
break;
case 12: monthName = "December";
}
return monthName;
}
static int getNumDaysInMonth (int m, int y) {
int numDaysInMonths= 0;
switch (m) {
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
numDaysInMonths= 31;
break;
case 4: case 6: case 9: case 11:
numDaysInMonths = 30;
break;
case 2:
if (isLeapYear(y))
numDaysInMonths = 29;
else
numDaysInMonths = 28;
break;
}
return numDaysInMonths;
}
static boolean isLeapYear (int y) {
return (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0);
// return true;
// return false;
}
static int getStartDay (int m, int y) {
// Adjust month number & year to fit Zeller's numbering system
if (m < 3)
m = m + 12;
y = y - 1;
int d = 1; //Set day parameter to 1
int k = y % 100; // Calculate year within century
int j = y / 100; // Calculate century term
int h = 0; // Day number of first day in month 'm'
h = ( d + ( 13 * ( m + 1 ) / 5 ) + k + ( k / 4 ) + ( j / 4 ) + ( 5 * j ) ) % 7;
// Convert Zeller's value to ISO value (1 = Mon, ... , 7 = Sun )
int dayNum = ( ( h + 5 ) % 7 ) + 1;
return dayNum;
}
}
I recommend you do it using the modern date-time API. Learn more about the modern date-time API from Trail: Date Time.
import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in); // Scan for user input
System.out.print("Please enter a month between 1 and 12 (e.g. 5): "); // Prompt user to enter month
int m = input.nextInt();
System.out.print("Please enter a full year (e.g. 2018): "); // Prompt user to enter year
int y = input.nextInt();
printMonth(y, m);
}
static void printMonth(int year, int month) {
YearMonth ym = YearMonth.of(year, month);
System.out.println("Sun Mon Tue Wed Thu Fri Sat");
int counter = 1;
// Get day of week of 1st date of the month and print space for as many days as
// distant from SUN
int dayValue = LocalDate.of(year, month, 1).getDayOfWeek().getValue();
for (int i = 0; i < dayValue; i++, counter++) {
System.out.printf("%-4s", "");
}
for (int i = 1; i <= ym.getMonth().length(ym.isLeapYear()); i++, counter++) {
System.out.printf("%-4d", i);
// Break the line if the value of the counter is multiple of 7
if (counter % 7 == 0) {
System.out.println();
}
}
}
}
A sample run:
Please enter a month between 1 and 12 (e.g. 5): 9
Please enter a full year (e.g. 2018): 2020
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Note: Learn about formatted printing at Formatter.
I don’t think your getStartDay method returns the day of week number that you expect. It seems to be returning 1 for Wednesday through 7 for Tuesday. Examples:
Month Start day of week getStartDay()
------------------------------------------------
July 2020 Wednesday 1
August 2020 Saturday 4
September 2020 Tuesday 7
October 2020 Thursday 2
There is probably one or two more problems in your code, but I think you should fix this fundamental one first.
It’s a fine exercise, you’re surely learning. For production code one would never implement Zeller’s algorithm or any other algorithm for finding lengths of months and days of week. This is done much more reliably by the standard library as shown in the answer by Arvind Kumar Avinash.
Related
My code compiles and runs perfectly, but when I any dates that are Saturdays the output is 'null' instead of 'SATURDAY'. Examples will be provided below to further explain this problem.
I have tried to change my if statement on my "getDayOfWeek" method but I seem to have no solution, I have also tried to obtain help from an experienced coder but they seem to be struggling due to java not being their main language...
The code:
class MyDate {
// properties of date object
private int day, month, year;
// constructor with arguments
public MyDate(int day, int month, int year) {
this.day = day;
this.month = month;
this.year = year;
}
public boolean isDateValid() {
if (month > 12 || month < 1 || day < 1) { // if values exceed 12 or are negative: return false
return false;
} else if (year <= 1582 && month <= 10 && day <= 15) { // starting date
// checking
return false;
} // for 31 day months: January, March, May, July, August, October, December
else if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
if (day > 31) {
return false;
}
} // for 30 day months: April, June, September, November
else if (month == 4 || month == 6 || month == 9 || month == 11) {
if (day > 30) {
return false;
}
} // February check
else if (month == 2) {
// leap year check for February
// 29 days in a leap year
// 28 days in a common year
if (isLeapYear()) {
if (day > 29) {
return false;
}
} else {
if (day > 28) {
return false;
}
}
}
return true;
}
// checks if input year is leap year
private boolean isLeapYear() {
if (year % 4 != 0) {
return false;
} else if (year % 400 == 0) {
return true;
} else if (year % 100 == 0) {
return false;
} else {
return true;
}
}
// method returns the day of MyDate object
public int getDay() {
return day;
}
// parameter for day to set
public void setDay(int day) {
this.day = day;
}
// method returns the month of MyDate object
public int getMonth() {
return month;
}
// parameter for month
public void setMonth(int month) {
this.month = month;
}
// method returns the year of MyDate object
public int getYear() {
return year;
}
// parameter for year
public void setYear(int year) {
this.year = year;
}
// method returns all variables: day/month/year of MyDate object
public String toString() {
return day + "/" + month + "/" + year;
}
}
public class MyCalendar {
//enums for days of week
public static enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
};
//enums for month of year
public static enum Month {
JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER;
};
//enums for week number of month
public static enum Week {
FIRST, SECOND, THIRD, FOURTH, FIFTH;
};
//to store Date object
private MyDate date;
//constructor taking mydate object
public MyCalendar(MyDate enteredDate) {
this.date = enteredDate;
}
//main method
public static void main(String[] args) {
boolean dateValid = false; //valid date false
Scanner input = new Scanner(System.in); //scanner for input
MyDate enteredDate = null;
//till valid date found
while (!dateValid) {
System.out.print("Enter the date as day month year : ");
//taking input and creating date output
enteredDate = new MyDate(input.nextInt(), input.nextInt(), input.nextInt());
//validating date input
if (enteredDate.isDateValid()) { //if valid
MyCalendar myCalendar = new MyCalendar(enteredDate);
//creating calendar table
myCalendar.printDateInfo(); //printing date info
myCalendar.printCalendar(); //printing calendar
dateValid = true; //setting validate to true
} else {
System.out.println(enteredDate + " is not a valid date, please re-input a valid date: ");
}
}
input.close();
}
// returns number of days in current month
private int getNumberOfDays() {
int days = 31;
int month = date.getMonth();
if (month == 4 || month == 6 || month == 9 || month == 11)
days = 30;
return days;
}
//print calendar of input month
public void printCalendar() {
System.out.println("\n\nThe Calendar of "+Month.values()[date.getMonth()-1]+" "+date.getYear()+" is :");
int numberOfMonthDays = getNumberOfDays();
Day firstWeekdayOfMonth = getDayOfWeek(1, date.getMonth(), date.getYear());
int weekdayIndex = 0;
System.out.println("Su Mo Tu We Th Fr Sa");
// The order of days depends on the input of date
// to display output of calendar
for (int day = 0; Day.values()[day] != firstWeekdayOfMonth; day++) {
System.out.print(" "); // this loop to print the first day in the
// correct place
weekdayIndex++;
}
for (int day = 1; day <= numberOfMonthDays; day++) {
if (day < 10)
System.out.print(day + " ");
else
System.out.print(day);
weekdayIndex++;
if (weekdayIndex == 7) {
weekdayIndex = 0;
System.out.println();
} else {
System.out.print(" ");
}
}
System.out.println();
}
//method to print about date information in literal form
public void printDateInfo() {
System.out.println(date + " is a " + getDayOfWeek(date.getDay(), date.getMonth(), date.getYear())
+ " located in the " + Week.values()[getWeekOfMonth() - 1] + " week of "
+ Month.values()[date.getMonth() - 1] + " " + date.getYear());
}
/*
* gets day of the week, returns enum type Day
*
* Zellar's congruence to calculate the day of week
* for any given date after October 15 1582
* (h) = (q+(13*(m+1)/5)+K+(K/4)+(J/4)+5J)%7 ,q- day of month,
* m- month, k = year of century (year%100), J = (year/100)
*/
public Day getDayOfWeek(int day, int month, int year) {
int q = day;
int m = month;
if (m < 3) {
m = 12 + date.getMonth();
year = year - 1;
}
int K = year % 100;
int J = year / 100;
//calculating h value
int h = (q + (13 * (m + 1) / 5) + K + (K / 4) + (J / 4) + 5 * J) % 7;
Day output = null;
if (h < Day.values().length && h > 0) {
output = Day.values()[h - 1]; //getting respective enum value
}
return output; //returning enum value
}
// get week number of current date
public int getWeekOfMonth() {
int days = date.getDay();
int weeks = days / 7;
days = days % 7;
if (days > 0)
weeks++;
return weeks;
}
}
Expected results:
java MyCalendar 29/02/2019
29/02/2019 in not a valid date, please re-input a valid date: 25/05/2019
25/05/2019 is a Saturday and located in the fourth week of May 2019
The calendar of May 2019 is:
SUN MON TUE WED THU FRI SAT
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Actual results:
25/05/2019 is a null located in the FOURTH week of MAY 2019
The calendar of May 2019 is:
SUN MON TUE WED THU FRI SAT
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Results of another date (that is not a Saturday):
24/05/2019 is a FRIDAY located in the FOURTH week of MAY 2019
The calendar of May 2019 is:
SUN MON TUE WED THU FRI SAT
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Specified problem:
The output prints null on all dates that are on the day of Saturday, whereas other dates that are not a Saturday will achieve the correct output needed.
if (h < Day.values().length && h > 0) {
should change to
if (h < (Day.values().length + 1) && h > 0) {
If this is for production code, the comment by Basil Bourque is correct: you should not develop your own MyDate class but rely on the built in LocalDate class.
If on the other hand, as I would assume, this is a programming exercise, it’s a fine one, and there’s no reason (that I can see) why you shouldn’t struggle your way through it.
Your formula for calculating the day of the week is:
//calculating h value
int h = (q + (13 * (m + 1) / 5) + K + (K / 4) + (J / 4) + 5 * J) % 7;
(As an aside, please find better variable names and also respect the Java naming convention: a variable name cannot be an uppercase letter.) I don’t understand the formula, but assuming that it is correct, it calculates the day of week as 0 = Saturday, 1 = Sunday up to 6 = Friday. To use this number as a lookup into your Day enum use
output = Day.values()[(h + 6) % 7]; //getting respective enum value
Since h will always be non-negative and less than 7, you don’t need the enclosing if statement. Just assign to output unconditionally. With these changes I get
Enter the date as day month year : 25 5 2019
25/5/2019 is a SATURDAY located in the FOURTH week of MAY 2019
The Calendar of MAY 2019 is :
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
I am not sure whether my solution is justifiable (ans. 171) - Project Euler Q.19 since I am having a hard time getting my head around modular arithmetic and not really sure whether my approach to it was correct or not... I was having trouble on trying to get the equivalence of having 0 as a key rather than 1 to Monday for reference in a hash table. The question was;
1 Jan 1900 was a Monday.
Thirty days has September, April, June and November. All the rest have thirty-one, Saving February alone, which has twenty-eight, rain
or shine. And on leap years, twenty-nine.
A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.
How many Sundays fell on the first of the month during the twentieth
century (1 Jan 1901 to 31 Dec 2000)?
So what I did was start the sum of days at 1 (reference for days in hash table) and subtract 1 after finding the sum of Sunday's, since doing it by 0 caused problems when the total sum of days were divisible by 3 and 6 (3:Wednesday, 6:Sunday). How could I have done this by using 0 as reference for Monday?
import java.util.*;
public class p19 {
public static void main(String[] args) {
Hashtable<Integer, String> days = new Hashtable<Integer, String>();
days.put(1, "Monday");
days.put(2, "Tuesday");
days.put(3, "Wednesday");
days.put(4, "Thursday");
days.put(5, "Friday");
days.put(6, "Saturday");
days.put(7, "Sunday");
Hashtable<Integer, String> months = new Hashtable<Integer, String>();
months.put(1, "January");
months.put(2, "February");
months.put(3, "March");
months.put(4, "April");
months.put(5, "May");
months.put(6, "June");
months.put(7, "July");
months.put(8, "August");
months.put(9, "September");
months.put(10, "October");
months.put(11, "November");
months.put(12, "December");
int min, max;
min = 1900;
max = 2000;
String[][] arr = new String[12 * (max - min + 1)][];
// Total days starts at 1 to make modular arithmetic easier when accounting for days
// (i.e., 1 Monday, 2 Tuesday, etc.) and since the first day, hence, 0th day on 1 Jan 1900 is Monday.
for (int year = min, index = 0, totalDays = 1; year <= max; year++) {
for (int month = 1; month <= 12; month++, index++) {
arr[index] = new String[numberOfDays(month,year)];
int sum = 1;
System.out.println(months.get(new Integer(month)) + " " + year);
for (int day = 1; day <= numberOfDays(month, year); day++, totalDays++) {
if (totalDays % 7 == 0) {
arr[index][day - 1] = days.get(new Integer((totalDays % 7 + 7) % 365));
}
else {
arr[index][day - 1] = days.get(new Integer((totalDays % 7) % 365));
}
if (sum > 7) {
System.out.println();
sum = 1;
}
System.out.print(totalDays + ":= " + arr[index][day - 1] + ", " + day + " | ");
sum++;
}
System.out.println("\n");
}
}
int count = 0;
for (int i = 1; i < arr.length; i++) {
if (arr[i][0] == "Sunday") {
count++;
}
}
// Subtract 1 from count since the total days were overstated by 1 before inititallizing array
System.out.println("Number of Sundays that fell on the first of the month from: 1/Jan/1901 - 31/Dec/2000: " + (count - 1));
}
public static int numberOfDays (int month, int year) {
int days = 0;
switch (month) {
case 7:
case 4:
case 6:
case 11:
days = 30;
break;
case 2:
if (isLeapYear(year)) {
days = 29;
}
else {
days = 28;
}
break;
default: days = 31;
break;
}
return days;
}
public static boolean isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
}
Your daysInMonth check is incorrect - the result must have been correct by incidence:
switch (month) {
case 4:
case 6:
case 9:
case 11:
days = 30;
break;
The rest of the program can be simplified - note that the start year has to be corrected too, dow stands for DayOfWeek:
public static void main (String[] args) {
int count = 0;
// dow = 2, since 1.1.1901 was a Thuesday (2)
for (int year = 1901, dow = 2; year <= 2000; ++year)
{
for (int month = 1; month <= 12; ++month)
{
if (dow == 0) {
// System.out.println ("Date: " + year + "-" + month);
++count;
}
dow = (dow + numberOfDays (month, year)) % 7;
}
}
System.out.println ("Number of Sundays that fell on the first of the month from: 1/Jan/1901 - 31/Dec/2000: " + count);
}
I'm trying to print out a calendar for an entire year given any year. The code starts each month on the correct day, but continues to count out seven number and returns the next line to the same starting column. How might I correct this?
Here is my current output:
2017
January
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
February
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
And continues on for the year. I believe the error is in the printCalendar method but I don't know what to do.
Here is my code:
import java.util.Scanner;
import java.io.*;
public class CalendarPrinter{
public static void main(String[]args)throws IOException{
Scanner kbd = new Scanner(System.in);
System.out.println("Calendar Printer\n");
System.out.print("Enter the year? ");
int year = kbd.nextInt();
printCalendar(year);
System.out.println("\n" + year + ".txt generated.");
}
public static void printCalendar(int year) throws IOException {
PrintWriter outputFile = new PrintWriter(year + ".txt");
outputFile.println(" " + year);
for(int month = 1; month <=12; month++) {
outputFile.println("\n " + getMonthName(month));
outputFile.println("Sun Mon Tue Wed Thu Fri Sat");
int numDays = getNumberofDays(month, year);
for(int day = 1; day <= numDays; day++){
int dayWeek = getDayofTheWeek(day, month, year);
for(int k = 0; k < dayWeek; k++)
outputFile.print(" ");
outputFile.printf("%3d ", day);
if(day % 7 == 0) {
outputFile.println("");
dayWeek = 0;
}
}
}
outputFile.close();
}
public static String getMonthName(int month){
String name;
switch(month){
case 1: name = "January";
break;
case 2: name = "February";
break;
case 3: name = "March";
break;
case 4: name = "April";
break;
case 5: name = "May";
break;
case 6: name = "June";
break;
case 7: name = "July";
break;
case 8: name = "August";
break;
case 9: name = "September";
break;
case 10: name = "October";
break;
case 11: name = "November";
break;
case 12: name = "December";
break;
default: name = "Unknown";
break;
}
return name;
}//method
public static int getNumberofDays(int month, int year){
int numDays;
switch(month){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
numDays = isLeap(year)? 29:28;
break;
default:
numDays = 0;
break;
}
return numDays;
}//method
public static boolean isLeap(int year){
if(((year % 4 == 0) && !(year % 100 == 0)) || (year % 400 == 0))
return true;
else
return false;
}
public static int getDayofTheWeek(int day, int month, int year){
int y = year - (14-month)/12;
int x = y+y/4 - y/100 + y/400;
int m = month + 12 * ((14-month)/12) -2;
int d = (day + x + (31*m)/12)%7;
return d;
}//method
}//class
Your approach to using the day of the week is what messes up your printed data. In this example I'm using a temporary array to save one row of days (a.k.a. one printed line). Once the 7th day of a week is stored in the array, we print the whole week. This also happens when the last day of the month is reached.
for (int month = 1; month <= 12; month++) {
outputFile.println("\n " + getMonthName(month));
outputFile.println("Sun Mon Tue Wed Thu Fri Sat");
int numDays = getNumberofDays(month, year);
int[] week = new int[7];
for (int day = 1; day <= numDays; day++) {
int dayWeek = getDayofTheWeek(day, month, year);
week[dayWeek] = day;
// did we reach the 7th day of the week or the last day of the month?
if ((dayWeek + 1) % 7 == 0 || day == numDays) {
// print the week as one row
for (int d : week) {
// don't print 0 values
outputFile.printf("%3s ", d == 0 ? "" : d);
}
outputFile.println("");
// reset the array to store a new row in the next loop iteration
week = new int[7];
}
}
outputFile.println("");
}
So basicaly, everything works like it should. But the main thing that should be correct, which is the date, is wrong, so far for october 2015 it is correct but for some reason i cannot detect, the other months i have tried so far are incorrect when compared to the calendar in my computer.
Here is my program, maybe you have some valid input to help me with these issues.
public static boolean isLeapYear(int year) {
int month = 0;
int s = getDaysIn(month, year);
return year % 4 == 0 && (year % 100 != 0) || (year % 400 == 0);
}
public static int getDaysIn(int month, int year) {
switch (month) {
case 1:
return 31;
case 2:
if (isLeapYear(month)) {
return 29;
} else {
return 28;
}
case 3:
return 31;
case 4:
return 30;
case 5:
return 31;
case 6:
return 30;
case 7:
return 31;
case 8:
return 31;
case 9:
return 30;
case 10:
return 31;
case 11:
return 30;
case 12:
return 31;
default:
return -1;
}
}
public static String getMonthName(int month) {
switch (month) {
case 1:
return "January";
case 2:
return "February";
case 3:
return "March";
case 4:
return "April";
case 5:
return "May";
case 6:
return "June";
case 7:
return "July";
case 8:
return "August";
case 9:
return "September";
case 10:
return "October";
case 11:
return "November";
case 12:
return "December";
default:
return "Invalid month.";
}
}
public static int getStartDay(int month, int year) {
int days = 0;
for (int i = 1900; i < year; i++) {
days = days + 365;
if (isLeapYear(i)) {
days = days + 1;
}
}
for (int i = 1; i < month; i++) {
days = days + getDaysIn(month, year);
}
int startday = (days + 1) % 7 + 2;
return startday;
}
public static void displayCalendar(int month, int year) {
String monthName = getMonthName(month);
int startDay = getStartDay(month, year);
int monthDays = getDaysIn(month, year);
System.out.println(" Sun Mon Tue Wed Thu Fri Sat");
int weekDay = startDay - 1;
for (int i = 1; i < startDay; i = i + 1) {
System.out.print(" ");
}
for (int x = 1; x <= monthDays; x++) {
weekDay = weekDay + 1;
if (weekDay > 7) {
System.out.println();
weekDay = 1;
}
System.out.format(" %3d", x);
}
if (weekDay > 7) {
System.out.println();
}
}
Your getStartDay is actually where your error lays :
for (int i = 1; i < month; i++) {
days = days + getDaysIn(month, year);
}
int startday = (days + 1) % 7 + 2;
return startday;
Should be replaced with :
for (int i = 1; i < month; i++) {
days = days + getDaysIn(i, year);
}
int startday = (days % 7) + 2;
return startday;
There is a minor problem with your loop as you see.
You should have had used your incrementor i in your getDaysIn calls to count the days from the begin of the year until the month you want to display.
Second error is here :
int startday = (days + 1) % 7 + 2;
The logic behind this expression is still a mystery for me.
Let's break this off with a concrete example :
Let's say we want to display FEB 1900. Easy to do because we start at the begin of JAN 1900 so we can count the days easily (31 days in january so days = 31)
Which result will the first expression return?
= (31 + 1) % 7 + 2
= 32 % 7 + 2
= 4 + 2
= 6
Because day 1 in your logic is SUNDAY, day 6 is FRIDAY.
Let's check it out :
Not really the expected result right?
I see one more problem with this method.
Let's imagine days = 33 (this will never happens but we need this example here).
= (33 + 1) % 7 + 2
= 34 % 7 + 2
= 6 + 2
= 8
What would the 8th day of the week be?
The explanation of the correct answer is the following :
(days % 7) + 2
days % 7 gives us the value of the last day of the following month when weeks begin with MONDAY.
To this value, we add 2 :
1 to have the beginning day of the wanted month.
1 because our calendar begins with sunday and we'll have to slide our days on the calendar view.
Here is the full code (that I also modified a bit to make it more compact) :
public class Calendar{
public static void main(String[] args) {
// INSERT YOUR TESTS HERE
}
public static boolean isLeapYear(int year) {
return year % 4 == 0 && (year % 100 != 0) || (year % 400 == 0);
}
public static int getDaysIn(int month, int year) {
switch (month) {
case 1 : case 3 : case 5 : case 7 : case 8 : case 10 : case 12 :
return 31;
case 4 : case 6 : case 9 : case 11 :
return 30;
case 2:
return isLeapYear(year) ? 29 : 28;
default:
return -1;
}
}
public static String getMonthName(int month) {
String[] months = {"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
return month <= 12 && month > 0 ? months[month - 1] : "Invalid month";
}
public static int getStartDay(int month, int year) {
int days = 0;
for (int i = 1900; i < year; i++) {
days += 365;
if (isLeapYear(i)) {
days = days + 1;
}
}
for (int i = 1; i < month; i++) {
days = days + getDaysIn(i, year);
}
int startday = (days % 7) + 2;
return startday;
}
public static void displayCalendar(int month, int year) {
String monthName = getMonthName(month);
int startDay = getStartDay(month, year);
int monthDays = getDaysIn(month, year);
System.out.println(" Sun Mon Tue Wed Thu Fri Sat");
int weekDay = startDay - 1;
for (int i = 1; i < startDay; i = i + 1) {
System.out.print(" ");
}
for (int x = 1; x <= monthDays; x++) {
weekDay = weekDay + 1;
if (weekDay > 7) {
System.out.println();
weekDay = 1;
}
System.out.format(" %3d", x);
}
if (weekDay > 7) {
System.out.println();
}
}
}
EDIT
You should try to write something in your main method if nothing displays.
public static void main(String[] args) {
for (int i = 0 ; i < 5 ; i++){
System.out.println(getMonthName(i+1) + " " + (2010 + i));
displayCalendar(i+1, 2010 + i);
System.out.println();
}
}
Gives the following output :
January 2010
Sun Mon Tue Wed Thu Fri Sat
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
February 2011
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28
March 2012
Sun Mon Tue Wed Thu Fri Sat
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
April 2013
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
May 2014
Sun Mon Tue Wed Thu Fri Sat
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
This question already has answers here:
Excluding Dates from Print Loop
(2 answers)
Closed 10 years ago.
I have almost completed my code; however, instead of eliminating solely the dates which fall on Friday and also happen to be the 13th day of the month, it has eliminated every 13th submission. I thought that:
int friday = ((startingDayOfWeek+dayOfYear) % 7);
if (dayOfYear != 13 && friday != 5)
System.out.println(month + "/" + dayOfYear);
dayOfYear++;
Would work, but it is eliminating them all. I understand that there are easier ways to accomplish this; however, I am required to do it in this manner. Here is the full code:
public class LoopDate {
public static void main(String[] args) {
//Denotes that Tuesday is the first day of 2013
int startingDayOfWeek = 2;
int year = 2013;
int numDays = 0;
for (int month = 1; month <= 12; month++) {
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) && !(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
int dayOfYear = 1;
while (dayOfYear <= numDays)
{
int friday = ((startingDayOfWeek+dayOfYear) % 7);
if (dayOfYear != 13 && friday != 5)
System.out.println(month + "/" + dayOfYear);
dayOfYear++;
}
}
}
}
Your boolean logic is wrong.
if (dayOfYear != 13 && friday != 5)
Should be:
if (dayOfYear != 13 || friday != 5)
You are doing the negative check of "is it friday the 13th". When converting a positive check into a negative check, you need to NOT the conditions (done), and flip the operators (OR becomes AND, AND becomes OR).
Also, when dealing with boolean logic like that, I usually give the segments meaningful names. It 'costs' a variable, but can save you countless hours later on!
boolean isFridayThe13th = (dayOfYear == 13 && friday == 5);
if (!isFridayThe13th) ...