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) ...
Related
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.
right now i have a problem that i want to run my code with this
i make to check februay on the case 2 if year is true than run the execute if statement if it was false it will go to default but right now it go to the case 3 statement how to solve that not go to the case 3 but go to the default?
//this is my code
public static void main(String[] args) {
getDaysInMonth(1, 2018);
System.out.println(getDaysInMonth(2, 2018));
}
public static boolean isLeapYear(int year) {
if(year < 1 && year > 9999) {
return false;
} else {
if(year % 4 == 0) {
return true;
} else if(year % 100 == 0) {
return false;
} else if(year % 400 == 0) {
return true;
} else {
return false;
}
}
}
public static int getDaysInMonth(int month, int year) {
if((month < 1 || month > 12) && (year < 1 || year > 9999)) {
return -1;
}
isLeapYear(year);
int days;
switch(month) {
case 1:
days = 31;
break;
case 2:
if(year == 1) {
days = 29;
break;
}
case 3:
days = 31;
break;
case 4:
days = 30;
break;
case 5:
days = 31;
break;
case 6:
days = 30;
break;
case 7:
days = 31;
break;
case 8:
days = 31;
break;
case 9:
days = 30;
break;
case 10:
days = 31;
break;
case 11:
days = 30;
break;
case 12:
days = 31;
break;
default:
days = 28;
break;
}
return days;
}
This happens because your break is in the IF scope -> then if the year not 1 its continue to case 3.
You can use if else clause:
case 2:
if(year == 1) {
days = 29;
} else {
days = 28;
}
break;
But I have to remind you, year != 1 does not mean its Feb get 28 days, maybe you want this:
case 2:
if(!isLeapYear(year)) {
days = 29;
} else {
days = 28;
}
break;
Aside from the question about if statements and switch, there are some problems to be addressed with the method for leap year checking first. Here is the beginning of original code below:
public static boolean isLeapYear(int year) {
if(year < 1 && year > 9999) {
return false;
} else {
...
The condition year < 1 && year > 9999 can never happen since year can't be both less than one and greater than 9999 at the same time so it's redundant.
Other than this, the algorithm for determining if a year is a leap year is as follows (in plain English):
See if the year is evenly divisible by 4. If not, it can't be a leap year (return false).
Here a year is evenly divisible by 4 (determined in step 1). If it is not evenly divisible by 100, it is a leap year (return true).
Here a year is evenly divisible by 4 and also by 100. If the year is also evenly divisible by 400 then it is a leap year. Otherwise it isn't.
Putting all of the above considerations into code, it can be made more readable:
public static boolean isLeapYear(int year) {
if (year % 4 != 0) {
// year is not evenly divisible by 4 (it has a remainder, can't be a leap year).
return false;
}
// year is evenly divisible by 4
if (year % 100 != 0) {
// divisible by 4 and not 100, it's a leap year
return true;
}
// divisible by 4 and also 100
if (year % 400 != 0) {
// divisible by 4, 100 and not by 400
return false;
}
// divisible by 4, 100 and 400
return true;
}
Considering your getDaysInMonth method, we have the following cases, with 1 = January, 2 = February and so on:
30 days: September (9), April (4), June (6), November (11)
31 days: All others but February (2) (28, 29 on a leap year)
public static int getDaysInMonth(int month, int year) {
switch (month) {
case 9:
case 4:
case 6:
case 11:
return 30;
case 2:
if (isLeapYear(year)) {
return 29;
} else {
return 28;
}
default:
return 31;
}
}
Regarding validation of arguments, if you are receiving user input, it should all be validated outside of the methods used for calculation (pass the methods input that's already been validated instead of validating directly inside them).
I have an assignment in Java (intro to programming) based on Zellers algorithm, Write input as integers, loop and counter code and I have to use a while loop to get the day and year first then the month, treating Jan & Feb as prior year. I thought I was at least in the ballpark, but cannot get my code to work. Any suggestions on how to improve?
import java.util.Scanner;
import java.text.NumberFormat;
public class ZellersAlgorithm {
public static void main(String[] args) {
//declarations go here
int count, Month, Day, Year;
int C = (int)(Year / 100.0); // the century
int D = (int) (Year % 100); // The year of the century
int K = Day;
int M = Month;
int G = (K + (int)((26 * (M + 1)) / 10.0) + C + (int)(C / 4.0)
+ (int)(D / 4.0) + (5 * D)) % 7;
Month = (M);
Day = (K);
Year = (C + D);
Scanner scan = new Scanner(System.in);
//Title
System.out.println("Project 2 - Zellers Algorithm");
while(M != 0){
System.out.print("Enter a numberic day: ");
K = scan.nextInt();
if (K == 0)
System.out.print("Saturday");
else if (K == 1)
System.out.print("Sunday");
else if (K == 2)
System.out.print("Monday");
else if (K == 3)
System.out.print("Tuesday");
else if (K == 4)
System.out.print("Wednesday");
else if (K == 5)
System.out.print("Thursday");
else
System.out.print("Friday");
System.out.print("Enter a nummeric year: ");
///Need to convert 4 digit year to C & D variable
// Add counter, possibly include length counter 1st 2 digits are century/C last 2 are year
Year = scan.nextInt();
System.out.print("Enter a numeric month: ");
M = scan.nextInt();
switch (M) {
case 1:
System.out.println("March");
break;
case 2:
System.out.println("April");
break;
case 3:
System.out.println("May");
break;
case 4:
System.out.println("June");
break;
case 5:
System.out.println("July");
break;
case 6:
System.out.println("August");
break;
case 7:
System.out.println("September");
break;
case 8:
System.out.println("October");
break;
case 9:
System.out.println("November");
break;
case 10:
System.out.println("December");
break;
case 11:
System.out.println("January" + D + count--);
break;
case 12:
System.out.println("February" + D + count--);
break;
default:
System.out.println("Invalid month.");
break;
}
}
//formula one
//G =([2.6M-.2]+K+D+[D/4]+[C/4]-2C mod 7;
//display as integer
String result = "Day of the week is ";
System.out.println();
Please clarify on what but cannot get my code to work means.
Some comments though
int count, Month, Day, Year; -- variables should be lower case (this does not change the behaviour of your program but is common code style for Java programs - Most people would read Year as a class name). The same goes for "all uppercase" like C, which is normally used for constants
Use variable names that express meaning. M, K, C, D do not help the reader to understand, what they mean.
I need to create a method for a program that accepts the date and if valid will add all the days from 01/01/xx to the date in the that year, eg 10/1/1999 will display "day 274 in 1999". I have the following code below, but its not adding the correct values. Not sure what I am doing wrong.
public static int dayNumber(int day, int month, int year){
int daysInMonth = 0;
int days = 0;
boolean leapYear = isLeapYear(year);
for(int i = 1; i <= month; i++){
switch(month){
case 1: daysInMonth += 31;
case 2: if(leapYear)
daysInMonth += 29;
else
daysInMonth += 28;
case 3: daysInMonth += 31;
case 4: daysInMonth += 30;
case 5: daysInMonth += 31;
case 6: daysInMonth += 30;
case 7: daysInMonth += 31;
case 8: daysInMonth += 31;
case 9: daysInMonth += 30;
case 10: daysInMonth += 31;
case 11: daysInMonth += 30;
case 12: daysInMonth += 31;
break;
default:
break;
}
while(month <= 12){
days += daysInMonth + day;
month++;
}
}
return days;
}
You need to terminate each case with a break:
case 1: daysInMonth += 31;
break;
case 2: if(leapYear)
daysInMonth += 29;
else
daysInMonth += 28;
break;
case 3: daysInMonth += 31;
break;
and so on.
Without this, statements in a switch fall through.
Additionally, your loop variable is i and you switch on month (but then modify month in another, nested, loop).
There is really no need for a loop here... This should do the trick:
days = day
days += (month-1)*30;
days += (month)/2; // every odd month until July has 31 days
days += (month >= 8 && month % 2 == 1) ? 1 : 0; // so if we have august or later and in an even month, add 1 day
if (month > 2) {
days -= (isLeapYear(year)) ? 1 : 2;
}
Just read your comment about this being exercise for school, so I'll better explain my code a little bit more.
First, we assume every month just has 30 days.
This, of course, is incorrect - every second month, starting with January, has 31. SO we're calculating how many month with 31 days we had so far. As it's the odd month (at least until August) that have the 31 days, we're dividing the month by two (remember - integer division, we'll get floor(month/2)) to get the number of month that have passed and had 31 days.
This is still incorrect, as starting with August, we have another day to add - our previous calculation yields one month with 31 days less than we really had. So we just add that one day if an even number of month has passed (we can tell this by dividing month by two and looking at the leftover, this is called "modulo division" and written "month % 2").
Finally, we're going for February. If February has passed (=we are in march or later) we just subtract two days - or one if it's a leap year. I used a so called "ternary statement" here (the ... ? ... : ... thing). Basically it's short for if (isLeapYear(year)) { days -= 1; } else { days -= 2; }
I am attempting to write a loop that will get its values from my switch statement. I want it to print out the dates in order each on their own line, such as:
1/1
1/2
1/3
...
12/31
I have attempted to write it myself, but I'm not entirely sure how to assign the months in correct order to the 3 cases I have in the switch statement.
Below is the switch statement I am using:
int month = 0;
int yearInt = year;
int totalDays = 0;
switch (month) {
case 1:
totalDays = 30;
break;
case 2:
if (((yearInt % 4 == 0) && !(yearInt % 100 == 0))
|| (yearInt % 400 == 0))
totalDays = 29;
else
totalDays = 28;
break;
default:
totalDays = 31;
break;
Like this? January is assumed 1
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
totalDays = 31;
break;
case 2:
if (((yearInt % 4 == 0) && !(yearInt % 100 == 0))
|| (yearInt % 400 == 0))
totalDays = 29;
else
totalDays = 28;
break;
default:
totalDays = 30;
break;
Note that the fall-through syntax I used is sometimes considered harmfull
You can as well get the desired result using built-in methods:
Calendar c = Calendar.getInstance();
c.set(Calendar.YEAR, yearInt);
c.set(Calendar.MONTH, month);
int totalDays = c.getActualMaximum(Calendar.DAY_OF_MONTH);
Note: Value of month starts from 0 (0 for January, 1 for February..).