I'm trying to create a class that accepts user input for a month then outputs the number of days in said month. Whenever I test my class it doesn't give me an output for the number of days but instead just multiplies the month number by 10. Why is this happening and what can I do to fix it?
Here's my code
import java.util.Scanner;
public class Appointment
{
public static void main(String[] args)
{
Scanner kin = new Scanner(System.in);
System.out.print("Enter a number that corresponds to a month: ");
int month = kin.nextInt();
System.out.print(month);
int Days = 0;
System.out.print(Days);
if ( month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12)
{
Days = 31;
}
else if ( month == 4 || month == 6 || month == 9 || month == 11)
{
Days = 30;
}
else if ( month == 2)
{
Days = 28;
}
}
public int getDays()
{
int Days = 0;
return Days;
}
{
} }
You didn't multiply your month by 10; you just printed a 0 immediately after the month. The print method doesn't place anything after what you want to print, not even a newline.
Enter a number that corresponds to a month: 2
20
^^
| \
| --- The `0` is from `Days`
------ The `2` is from `month`
Output a space or some other verbiage, or use println to output a newline after your output, to visually distinguish the two variables' output.
Also, print Days after you get it assigned properly, after all those if statements, so it's not 0 when it's printed.
Your code is fine, but you should use
System.out.println() instead of
System.out.print()
The problem is that you are printing first your month and then, inmediately after the number 0 (variable days) in the SAME Line.
Suggestion for next time, use a debugger :)
You just print out month and then 0 without space. Also in your code your method getDays() never called. It full of mistakes.
Related
I am trying to write a program which shows the number of days in a given month of a year. The outputs for the month of February, non leap years (no output) and the months having 30 days in leap years is incorrect (output is 29). How could I resolve this?
public class Q11 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner number1 = new Scanner(System.in);
Scanner number2 = new Scanner(System.in);
System.out.println("Enter the month (1-12)");
int month = number1.nextInt();
System.out.println("Enter the year");
int year = number2.nextInt();
int number_of_days = 0;
boolean N1 = (month == 1) ||
(month == 3) ||
(month == 5) ||
(month == 7) ||
(month == 8) ||
(month == 10) ||
(month == 12);
boolean N2 = (month == 2) && (year % 400 == 0) || (year % 4 == 0 && year % 100 != 0);
boolean N3 = (month == 2) && (year % 400 <= 1) || (year % 4 <= 1) && (year % 100 == 0);
boolean N4 = (month == 4) ||
(month == 6) ||
(month == 9) ||
(month == 11);
if (N1)
System.out.println(". This month has 31 days");
else if (N2)
System.out.println(". This month has 29 days");
else if (N3)
System.out.println(". This month has 28 days");
else if (N4)
System.out.println(". This month has 30 days");
}
}
Problem
You run into a problem due to the fact how the program evaluates your boolean expressions. Remember the rules for boolean precedence. && is evaluated first and takes precedence. Also, the formula is evaluated from left to right. Operator precedence can be overruled with the correct setting of parentheses.
E.g. if you have a && b || c, a && b is evaluated first, after which we evaluate its result against || c. But: a && (b || c) is evaluated by first evaluating b || c and then evaluating this result against && a.
In your case, when you enter e.g. month = 4 and year = 2020 the following happens:
The rule n1 is skipped - month is not listed.
The rule n2 is evaluated - month is not equals to two and the year is not divisible by 400; so far everything goes to plan. But now - the next || comes around to bite you. The year is divisible by 4 AND it is not divisible by 100. The program now incorrectly prints 29.
The rules n3 and n4 are solved like n2 and are left as an exercise for the reader :)
Solution
Easiest way is to understand why n2 is failing and optimize the formula. Since this is a homework task I don't want to solve it for you.
General
One scanner instance on System.in is enough.
Your variable names should follow the Java naming convention, lowerCaseCamelCase instead of snake_case and N1.
Parting thought
Try using a switch statement on month - it will make your code a bit easier to understand. Finally: Good luck in your studies.
In your existing code make the following changes.
this checks for leap year.
if it is divisible by 4 and not a century year, its is a leap year
or if is divisible by 400 it is a leap year.
otherwise, it isn't.
boolean N2 = (year %4 == 0 && year %100 != 0) || (year % 400 == 0);
Now just use the negation of the boolean to test for non leap year.
if (N1)
System.out.println(". This month has 31 days");
else if (N4) {
System.out.println(". This month has 30 days");
} else if (month == 2) {
boolean N2 = (year %4 == 0 && year %100 != 0) || (year % 400 == 0);
if (N2) {
System.out.println("This month has 29 days");
} else {// must not be leap year.
System.out.println("This month has 28 days");
}
} else {
System.out.printf("Bad month(%d) entered", month);
}
Also, you should only use one Scanner for all console input.
An alternative approach
In case you didn't know, the enhanced switch statement introduced in Java 13 would be perfect for this.
it takes multiple cases
and returns an argument for processing.
public class Q11 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the month (1-12)");
int month = scanner.nextInt();
System.out.println("Enter the year");
int year = scanner.nextInt();
boolean isLeapYear = (year %4 == 0 && year %100 != 0) || (year % 400 == 0);
String proclamation = switch(month) {
case 1,3,5,7,8,10,12 -> "This month has 31 days.";
case 4,6,9,11 -> "This month has 30 days";
case 2 -> "This month has %d days".formatted(isLeapYear ? 29 : 28);
default -> "Bad month (%d) entered.".formatted(month);
};
System.out.println(proclamation);
}
}
The code works when the first year is a leap year so if I said the year was 2004 it would return 2008, but when the starting year is not a leap year, it returns nothing. How would I output that if, for ex: the given year was 2001, 2002, or 2003, the next leap year would be 2004. I know the while loop makes sense but I don't know what to put inside it. ALSO I can only use basic java formatting so no inputted classes like java.time.Year
public static boolean leapYear(int year) {
boolean isLeap = true;
if (year % 4 == 0) {
if (year % 100 == 0) {
if (year % 400 == 0)
isLeap = true;
else
isLeap = false;
} else
isLeap = true;
} else {
isLeap = false;
}
return isLeap;
}
public static int nextLeapYear(int year) {
int nextLeap = 0;
if (leapYear(year)) {
nextLeap = nextLeap + 4;
} else {
while (!leapYear(year)) {
nextLeap++;
}
nextLeap += 1;
}
year += nextLeap;
return year;
}
Granted this doesn't take much processing. But if you want to increase the efficiency of your program you might consider the following:
All leap years must be divisible by 4. But not all years divisible by 4 are leap years. So first, check for not divisible by 4. That will be 75% of the cases. In that event, return false.
if (year % 4 != 0) {
return false;
}
As you continue, the year must be divisible by 4 so just make certain it is not a century year. This will be evaluated 25% of the time and will return true 24% of the time.
if (year % 100 != 0) {
return true;
}
lastly, the only category not checked are years divided by 400. If we got here in the logic, then it must be a century year. So return accordingly. This will evaluate to true .25% of the time.
return year % 400 == 0;
Your code is broken in multiple ways:
You say: If the given year is a leap year, then the next leap year will be 4 years later. This is false. If you pass in 1896, your algorithm returns 1900, but this is wrong; whilst 1896 is a leap year, 1900 is not.
Your isLeapYear code would be miles easier to read if you early-exit. That method should have a lot of return statements and fall less indentation.
Your while loop will keep asking the same question over and over, and if you ask the same question to a stable method (and your isLeapYear method is stable), you get the same answer, resulting in an infinite loop. Presumably, you don't want while(!leapYear(year)), you want while(!leapYear(year + nextLeap)), and you don't want to increment nextLeap once more after the while loop.
in fact, your edge case of: If the stated year is already a year, add 4 - is not necessary at all. Think about it: You can just eliminate that if/else part. Your code will just be nextLeap, that while loop, and a return statement. a 3-liner, if you do right.
EDIT: I figured it out yay!
for anybody struggling w/ this, this is what worked for me :)
public static boolean leapYear(int year) {
if(year % 4 == 0)
{
if( year % 100 == 0)
{
// year is divisible by 400, hence the year is a leap year
if ( year % 400 == 0)
return true;
else
return false;
}
else
return true;
}
else
return false;
}
public static int nextLeapYear (int year) {
int nextLeap = 0;
while(leapYear(year + nextLeap) == false){
nextLeap++;
}
if(leapYear(year) == true)
nextLeap += 4;
year += nextLeap;
return year;
}
Every year that is exactly divisible by four is a leap year, except
for years that are exactly divisible by 100, but these centurial years
are leap years if they are exactly divisible by 400. For example, the
years 1700, 1800, and 1900 are not leap years, but the years 1600 and
2000 are.
- United States Naval Observatory
You can greatly simplify the function, leapYear as shown below:
public static boolean leapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
Demo:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(leapYear(1999));
System.out.println(leapYear(2000));
System.out.println(leapYear(1900));
System.out.println(leapYear(1904));
}
public static boolean leapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
}
Output:
false
true
false
true
Then, you can use it in the function, nextLeapYear as shown below:
public class Main {
public static void main(String[] args) {
// Test
System.out.println(nextLeapYear(1999));
System.out.println(nextLeapYear(2000));
System.out.println(nextLeapYear(2001));
}
public static int nextLeapYear(int year) {
// If year is already a leap year, return year + 4
if (leapYear(year)) {
return year + 4;
}
// Otherwise, keep incrementing year by one until you find a leap year
while (!leapYear(year)) {
year++;
}
return year;
}
public static boolean leapYear(int year) {
return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
}
}
Output:
2000
2004
2004
In production code, you should use the OOTB (Out-Of-The-Box) class, java.time.Year to deal with a year.
import java.time.Year;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(nextLeapYear(1999));
System.out.println(nextLeapYear(2000));
System.out.println(nextLeapYear(2001));
}
public static int nextLeapYear(int year) {
Year yr = Year.of(year);
// If year is already a leap year, return year + 4
if (yr.isLeap()) {
return yr.plusYears(4).getValue();
}
// Otherwise, keep incrementing year by one until you find a leap year
while (!yr.isLeap()) {
yr = yr.plusYears(1);
}
return yr.getValue();
}
}
Output:
2000
2004
2004
Learn more about the modern date-time API at Trail: Date Time.
It seems it not easy to get nextLeapYear() 100 % correct. Allow me to suggest a simpler way of thinking about it that will also — so I believe — make it simpler to code correctly and/or fix any bug there may be.
Declare a variable candidateLeapYear to hold a year that we don’t yet know whether will be the next leap year after year. Initialize it to year + 1 since we know that the next leap year will need to be strictly greater than year. In a loop test whether candidateLeapYear is a leap year (use the other method), and as long as it isn’t, increment by 1. When the loop terminates, candidateLeapYear holds the next leap year. Return it.
I've only just started college, and one of the first things we're learning is Java. I'm currently learning about if statements. For one of my homework assignments, I need to write a program that asks for the user to input a year. Then, the program needs to determine whether that year is a leap year or not.
The question states that if the year is divisible by 4, it is a leap year. Also, if the year is divisible by 100, it should also be divisible by 400 in order to be a leap year.
This is what I've written so far:
System.out.print("Type a year: ");
int year = Integer.parseInt(reader.nextLine());
if (year % 4 == 0 || year % 100 == 0 && year % 400 == 0) {
System.out.print("The year is a leap year.");
} else {
System.out.print("The year is not a leap year.");
}
I'm expecting the program to check if the year is divisible by 4, or if the year is divisible by both 100 and 400.
Right now, when I enter the year 1800, the output says the year is a leap year, but I'm expecting it to say it is not a leap year. I suspect this is because the if statement is true when one of the conditions is true, which is the case because 1800 is divisible by 4. However, I can't seem to find out the right way to do it. Help would be much appreciated.
Your expression is asking "Is year a multiple of four or is it a multiple of 100 and also a multiple of 400?" The second half is entirely redundant because any multiple of both 100 and 400 was already a multiple of 4 in the first place (same with 400 and 100 also) and the result is clearly more inclusive than you intended.
Remember that a series of AND'd conditions will restrict the scenarios that match while ORs will broaden it. So start with finding multiples of four and then refine that a bit by adding in the secondary condition about multiples of 100.
year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) /* right! */
Since A(B+C) is equivalent to AB+AC in Boolean logic you could also expand this and it might read more clearly to you:
(year % 4 == 0 && year % 100 != 0) || (year % 4 == 0 year % 400 == 0) /* expanded */
The parentheses aren't really necessary but I left them for clarity.
Another perspective that might help you think about this is reversing the condition to find the years that aren't leap years. It's very similar in structure to the one you attempted so I think that studying it might give you some insight where your thought process went wrong:
year % != 0 || (year % 100 == 0 && year % 400 != 0) /* NON-leap years */
Finally, one last thing to point out is that it only takes either side of an OR to be true for the whole expression to be true. Looking back at your original logic, once the program has determined that year % 4 == 0 is true the rest of it is extra work that doesn't need to be performed. The program will actually skip those steps and this concept is called short-circuiting.
Another way to word the leap year criteria is this: if the year is divisible by 4 but not by 100, or it is divisible by 400, it is a leap year.
It's the "but not by 100" part that is not expressed in your code.
Example 1 (your fixed code):
System.out.print("Type a year: ");
int year = Integer.parseInt(reader.nextLine());
if (year % 100 == 0 && year % 400 == 0) || (year % 100 != 0 && year % 4 == 0) {
System.out.print("The year is a leap year.");
} else {
System.out.print("The year is not a leap year.");
}
Example 2 (other if for better understand)
System.out.print("Type a year: ");
int year = Integer.parseInt(reader.nextLine());
boolean isLeap = false;
if(year % 100 == 0){
if(year % 400 == 0)
isLeap = true;
} else if (year % 4 == 0){
isLeap = true;
}
System.out.print(isLeap ? "The year is a leap year." : "The year is not a leap year.");
Since any number divisible by 400 or 100 would, obviously, be divisible by 4. We would need to add additional check to make sure the year is a leap year
class Scratch {
public static void main(String[] args) {
for (int i = 1800; i <= 2000; i++) {
if (i % 4 == 0) {
if ((i % 100 == 0 && i % 400 == 0) || (i % 100 != 0)) {
System.out.println(i + ": A leap Year");
} else {
System.out.println(i + ": Not a leap year");
}
} else {
System.out.println(i + ": Not a leap year");
}
}
}
}
I am trying to write a program in Java (this is a school assignment that tells you what day of the week a certain date is. (The date should be written on the form yyyy-mm-dd.) I thought I had come up with a solution with the code below, but then I found an error.
When you run the code, and type in 1999-12-31 in the dialog, the program tells you that the entered date (1999-12-31) is a Friday. But when you type in the date 2000-01-01 (which is one day after 1999-12-31), the program tells you that the day is a Sunday! What happened with Saturday? A similar problem happens when you type in 2000-02-29 and 2000-03-01, they both give Wednesday as an answer!
What I have yet noticed, this error appears only when you enter a date between 2000-01-01 and 2000-02-29. I would be very grateful if someone could please help me to find the cause of the error and to solve the problem!
import static javax.swing.JOptionPane.*;
import static java.lang.Math.*;
public class DateCalc {
// Here, between the DateCalc class declaration and the main method, several methods used in the program are
// constructed.
// The method isLeapYear tests whether the entered year is a leap year or not.
private static boolean isALeapYear(int year) {
// If the year is a multiple of 4 and not a multiple of 100, or a multiple of 400, then it is a leap year.
if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
return true;
}
else {
return false;
}
}
// A method that tests whether a given string is written as a valid date.
private static boolean isAValidDate(int year, int month, int day) {
int maxValidYear = 9999;
int minValidYear = 1754;
if (year > maxValidYear || year < minValidYear) {
return false;
}
if (month < 1 || month > 12) {
return false;
}
if (day < 1 || day > 31) {
return false;
}
// Handle the February Month
if (month == 2) {
if (isALeapYear(year)) {
return (day <= 29); // This statement is true if the value of the day is less than or equal to 29 if the month is February within a leap year.
// Otherwise the statement is false and the method will return the boolean value false.
}
else {
return (day <= 28); // This statement is true if the value of the day is less than or equal to 28 if the month is February within a non-leap year.
// Otherwise the statement is false and the method will return the boolean value false.
}
}
// Month of April, June, September and November must have number of days less than or equal to 30.
if (month == 4 || month == 6 || month == 9 || month == 11) {
return (day <= 30);
}
return true;
}
// A method that calculates the day number within the year.
private static int dayNumberWithinYear(int year, int month, int day) {
// An array which stores the number of days in the different months (when the year is not a leap year).
// (Index 0 is the number of days in January, index 1 is the number of days in February, etc.)
int[] monthStructure = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
// If the entered year is a leap year, then the monthStructure array will be initialized with an extra day in February, i.e the leap day.
if (isALeapYear(year)) {
monthStructure[1] = 29;
}
int sumDaysInPreviousMonths = 0;
int daysInTheCurrentMonth = day;
int dayNumber = 0;
// Loops through all the months (index 0 is January, index 1 is February, etc.).
for (int i = 0; i < month - 1; i++) {
sumDaysInPreviousMonths += monthStructure[i];
}
dayNumber = sumDaysInPreviousMonths + daysInTheCurrentMonth;
return dayNumber;
}
// A method that decides the day of the week of an entered date.
private static void weekDay(int year, int month, int day) {
// The number of days that have passed since January 1, 1754, excluding the days of the entered year and
// excluding the leap days.
int sumDaysInOrdinaryYears = (year - 1754) * 365;
int sumLeapDaysInLeapYears = 0;
// Suppose the entered year is n. The for-loop goes through all the years from year n-1 to year 1754, and
// checks if the current year in the loop is a leap year. The number of leap years between year 1754 and n-1
// is equal to the number of days that will get added (beside from the days in ordinary years) to the total
// days from January 1, 1754 to the entered date.
for (; year > 1754; year -= 1) {
if (isALeapYear(year)) {
sumLeapDaysInLeapYears += 1;
}
}
// The sum of all days from year 1754 to year n-1 (if the entered year is n), is equal to the sum of days in
// the ordinary years and the leap days in the years.
int sumDaysInEveryYearExcludingTheEntered = sumDaysInOrdinaryYears + sumLeapDaysInLeapYears;
int sumDaysInTotalYears = sumDaysInEveryYearExcludingTheEntered + dayNumberWithinYear(year, month, day);
int weekDay = sumDaysInTotalYears % 7;
if (weekDay == 0) {
showMessageDialog(null, "The date is a monday.");
}
else if (weekDay == 1) {
showMessageDialog(null, "The date is a tuesday.");
}
else if (weekDay == 2) {
showMessageDialog(null, "The date is a wednesday.");
}
else if (weekDay == 3) {
showMessageDialog(null, "The date is a thursday.");
}
else if (weekDay == 4) {
showMessageDialog(null, "The date is a friday.");
}
else if (weekDay == 5) {
showMessageDialog(null, "The date is a saturday.");
}
// If weekDay == 6
else {
showMessageDialog(null, "The date is a sunday.");
}
}
public static void main(String[] args) {
// This is step 3 in the laboratory instruction.
while (true) {
String date = showInputDialog("Please, enter a date on the form yyyy-mm-dd");
// If the user clicks 'Cancel' or clicks 'OK' when the dialog box is empty, the program will exit.
if (date == null || date.length() == 0) {
break;
}
int y = Integer.parseInt(date.substring(0,4));
int m = Integer.parseInt(date.substring(5,7));
int d = Integer.parseInt(date.substring(8));
if (!isAValidDate(y, m, d)) {
showMessageDialog(null, "Error! The entered date is invalid. " +
" Please enter a valid date on the form yyyy-mm-dd");
}
else {
weekDay(y, m, d);
}
}
}
}
Instead of asking us to debug through your entire code, perhaps consider LocalDate to get the desired result:
LocalDate ldt = LocalDate.parse("1999-12-31");
System.out.println(ldt.getDayOfWeek());
LocalDate ldt2 = LocalDate.parse("2000-01-01");
System.out.println(ldt2.getDayOfWeek());
Output:
FRIDAY
SATURDAY
The Problem is with finding the number of leap year. Your logic is counting the year 2000 also. The number of leap years should be same for 1999-12-31 and 2000-01-01. You need to consider year 2000 only if the month is greater than February. Increment the sumLeapDaysInLeapYears only if the input date is greater than Feb 28th
So basically we have this question to do : Write a method dayNumber that determines the number of days in a year up to and including the current day. The method should have three int parameters: year, month, and day. If the value of any parameter is invalid, the method should print a warning message and return the value zero. The table gives some examples of the action of the method. Accept any non-negative year as being valid. You may want to assume the existence of a method numberOfDays that returns the number of days in a given month of a given year. And you should have a method call isLeapYear, if the user enter a year that is a leap year.
This is what I did so far....
class dayMonthYear {
public static void main(String[] args) {
System.out.println("Enter a year");
int year = In.getInt();
System.out.println("Enter the month for '1' to be January - '12' to be december");
int month = In.getInt();
System.out.println("Enter the day");
int day = In.getInt();
dayNumber(year, month, day);
System.out.println(dayNumber(year, month, day));
}
public static int dayNumber(int year, int month, int day) {
int total = 0;
for (int m = 1; m < month; m++)
total += (numberOfDays(month, year));
return total + day;
}
public static boolean isLeapYear(int yearB) {
return (yearB % 4 == 0 && yearB % 100 != 0) || yearB % 400 == 0;
}
public static int numberOfDays(int monthA, int yearA) {
int days = 0;
if (monthA == 4 || monthA == 6 || monthA == 9 || monthA == 11)
days = 30;
if (monthA == 1 || monthA == 3 || monthA == 5 || monthA == 7
|| monthA == 8 || monthA == 10 || monthA == 12)
days = 31;
else if (monthA == 2 && isLeapYear(yearA))
days = 29;
else if (monthA == 2)
days = 28;
return days;
}
}
It works and compiles but my problem is that: let say I enter "12" for December and December has 31 days, so what my program will do since December has 31 days, it thinks each month has 31 days and add them up which will give me 372 when it's suppose to give me 365. How do I make it that it won't do that and that it will work if the year is a leap year too.
Basically, this...
for (int m= 1; m < month; m++)
total += (numberOfDays(month, year));
is wrong, you are passing the value of month to this method each time it is called (12 for example), meaning that each time you call it, it thinks the number of days in the month is 31 (because it is)...
Instead, pass m
for (int m= 1; m < month; m++)
total += (numberOfDays(m, year));