Java code to display number of years till next leap year [closed] - java

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I wrote code to check whether the year entered is a leap year
or not. But now I am trying to add on so that If it is not, then my program must display the number of years until the next leap year. This is how I did The code for the first bit of my program

Turn this into a function that returns true/false based on a parameter. Then do the initial check, and after that a simple for loop from year to year + 4, and call the function with these new values.
public static void main(String args[]) {
int year = 2021;
System.out.println(IsLeapYear(year));
for (int i = year; i < year + 4; i++) {
if (IsLeapYear(i)) {
System.out.println("The next leap year is " + i);
break;
}
}
}
public static boolean IsLeapYear(int year) {
return ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0));
}
Output:
false
The next leap year is 2024*/
As per #mcemperor's request, here is a version with a while loop, which works correctly:
public static void main(String args[]) {
int year = 2020;
int i = year;
System.out.println(IsLeapYear(year));
while (!IsLeapYear(++i));
System.out.println("The next leap year is " + i);
}
public static boolean IsLeapYear(int year) {
return ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0));
}

You can find the closest leap yea by using an iterator (generator) to compute each successive leap year:
import java.time.LocalDateTime;
public class LeapYearDemo {
public static void main(String [] args) {
System.out.println(closestLeapYear(LocalDateTime.now()));
}
public static int closestLeapYear(LocalDateTime date) {
return LeapYearIterator.isLeapYear(date.getYear())
? date.getYear()
: new LeapYearIterator(date.getYear()).next();
}
}
import java.util.GregorianCalendar;
import java.util.Iterator;
public class LeapYearIterator implements Iterator<Integer>, Iterable<Integer> {
private static final GregorianCalendar CALENDAR;
private int year;
static {
CALENDAR = (GregorianCalendar) GregorianCalendar.getInstance();
}
public LeapYearIterator(int yearStart) {
this.year = yearStart;
}
#Override
public Integer next() {
do this.year++;
while (!isLeapYear(this.year));
return this.year;
}
#Override
public boolean hasNext() { return true; }
#Override
public Iterator<Integer> iterator() { return this; }
public static boolean isLeapYear(int year) {
return CALENDAR.isLeapYear(year);
}
}
I based this on some JavaScript code I wrote below.
const isLeapYear = (year) =>
year % 400 === 0 || (year % 4 === 0 && year % 100 !== 0);
function* nextLeap(date) {
let year = date.getFullYear() + 1;
while (true) {
if (isLeapYear(year++)) {
yield (year - 1);
}
};
};
const closestLeapYear = (date) =>
isLeapYear(date.getFullYear())
? date.getFullYear()
: nextLeap(date).next().value;
console.log(closestLeapYear(new Date()));

Related

JAVA call factory methods implicitly

I have 1 constructor and 1 factory method for my Date class. The first one just have 3 int parameter represent month, day and year. And the second one, I provide it in case user give string as one parameter to represent month/day/year.
As you can see in the main(), I forget to call parseIt, the factory method. But compiler still provide correct result. So question is: can JAVA call this factory method implicitly?
Please take a look the 1st constructor and 2nd factory methods:
import java.io.*;
class Date {
private int month;
private int day;
private int year;
public Date(int month, int day, int year) {
if (isValidDate(month, day, year)) {
this.month = month;
this.day = day;
this.year = year;
} else {
System.out.println("Fatal error: Invalid data.");
System.exit(0);
}
}
public static Date parseIt(String s) {
String[] strSplit = s.split("/");
int m = Integer.parseInt(strSplit[0]);
int d = Integer.parseInt(strSplit[1]);
int y = Integer.parseInt(strSplit[2]);
return new Date(m, d, y);
}
public static boolean isLeapYear(int year) {
if (year%4 != 0) {
return false;
} else if (year%100 == 0 && year%400 != 0) {
return false;
}
return true;
}
public static int daysInMonth(int month, int year) {
if (month == 2) {
if (isLeapYear(year)) {
return 29;
} else {
return 28;
}
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
return 31;
}
}
public static boolean isValidDate(int month, int day, int year) {
if (year < 1 || year > 9999 || month <= 0 || month > 12 || day <= 0) {
return false;
} else if (day > daysInMonth(month, year)) {
return false;
}
return true;
}
public static void main(String[] argv) {
Date d1 = new Date(1, 1, 1);
System.out.println("Date should be 1/1/1: " + d1);
d1 = new Date("2/4/2");
System.out.println("Date should be 2/4/2: " + d1);
}
}
No, it will not. There is no constructor which takes in a string, so it would throw a syntax error. In order to make it work, you would have to define a constructor which takes in a String parameter performs the same logic as the parseIt(String) function.

Comparing two dates using Comparable interface

I am currently designing a GUI for a bank database application. In my GUI I have a "List accounts opened before" button that I am trying to code to list all of the accounts in the database in a text area that have dates before a date that the user inputs into a text field. I am very confused about the implementation behind a Comparable interface and how to correctly compare two dates in a array of objects. In my mind my ShowBefore methods logic is correct, however I think that is not the case and I do not know why. My problem is with the BankDatabase's showBefore() method, Date's compareTo() method, and the GUI's ShowAllActions button. Any help would be greatly appreciated. I receive
"Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at BankDatabase.showBefore(BankDatabase.java:234)
at TransactionManager.showAllAccountsActionPerformed(TransactionManager.java:474)
at TransactionManager.access$1200(TransactionManager.java:17)
at TransactionManager$13.actionPerformed(TransactionManager.java:202)
"
When I input any date into the gui.
*I only posted the bare minimum methods required
public class BankDatabase
{
private static final int GROW_SIZE = 2;
private static final int NOT_FOUND = -1;
private static final int ARRAY_SIZE = 100; //i added this
private Account[] bank;
private int num;
/**
default constructor
*/
public BankDatabase()
{
num = 0;
bank = new Account[ARRAY_SIZE];
}
public String showBefore( Date prevDate)
{
String temp = new String();
for ( int i = 0; i < size(); i++)
{
if ( bank[i].getDate().compareTo(prevDate) == -1 )
{
temp += bank[i].toString(); //
temp += "\n";
}
}
return temp;
}
import java.util.Calendar;
import java.util.StringTokenizer;
public class Date implements Comparable {
private int invalidCheck = 0;
private int day;
private int month;
private int year;
/**
Parameterized Constructor.
#param d date
*/
public Date(String d)
{
StringTokenizer st = new StringTokenizer(d, "/");
month = Integer.parseInt(st.nextToken());
day = Integer.parseInt(st.nextToken());
year = Integer.parseInt(st.nextToken());
}
/**
Copy Constructor.
#param d date
*/
public Date(Date d)
{
month = d.month;
day = d.day;
year = d.year;
}
/**
Creates an instance with todays date
*/
public Date()
{
Calendar c = Calendar.getInstance();
this.day = c.get(Calendar.DAY_OF_MONTH);
this.month = c.get(Calendar.MONTH) + 1;
this.year = c.get(Calendar.YEAR);
}
/**
Compare “this” with (Date) o; if “this” is before o, return -1; if “this” is equal
to o return 0; if “this” is after o, return 1.
#param o
#return the value of the date
*/
public int compareTo(Object o)
{
Date d = new Date((Date) o);
if(d.year > year)
return -1;
if(d.year < year)
return 1;
if(d.month > month)
return -1;
if(d.month < month)
return 1;
if(d.day > day)
return -1;
if(d.day < day)
return 1;
return 0;
}
/**
checks to see if certain dates are valid. Also checks
if it is a leap year to verify the correct amount of days
in February.
#return true if the date is valid, false otherwise
*/
public boolean isValid()
{
if (( month == Month.JAN || month == Month.MAR
|| month == Month.MAY || month == Month.JUL
|| month == Month.OCT || month == Month.OCT
|| month == Month.DEC )
&& ( day <= Month.DAYS_ODD && day > invalidCheck ) )
return true;
if (( month == Month.APR || month == Month.JUN
|| month == Month.SEP
|| month == Month.NOV )
&& ( day <= Month.DAYS_EVEN && day > invalidCheck ) )
return true;
boolean leapYear = false;
if ( year % Month.QUADRENNIAL == invalidCheck
|| year % Month.CENTENNIAL == invalidCheck
|| year % Month.QUATERCENTENNIAL == invalidCheck )
{
leapYear = true;
}
if (leapYear)
{
if (month == Month.FEB && day <= Month.DAYS_FEB + 1)
return true;
}
if (month == Month.FEB && day <= Month.DAYS_FEB)
return true;
return false;
}
/**
Return the name and date of the TeamMember as a String.
#return name::price as a string.
*/
public String toString()
{
return month + "/" + day + "/" + year;
}
/**
day,month, and year are equal if they have the
same day, month, and year
#param obj
#return true if they are equal, false otherwise.
*/
public boolean equals(Object obj)
{
if (obj instanceof Date)
{
Date d = (Date) obj;
return d.day == day && d.month == month && d.year == year;
}
return false;
}
}
public abstract class Account
{
private static int numAccount = 1000; //incremented by 1 for each acc op.
protected final int PERCENTAGE = 100;
protected final int MONTH_PER_YEAR = 12;
protected Profile holder; //account holder's profile
protected int accNumber; //a sequence number from numAccount
protected double balance;
protected Date openOn; //the date the account is opened on
/**
parameterized constructor
#param name String that will be the name
#param phone String that will be the phone associated with the account
*/
public Account(String name, String phone)
{
holder = new Profile(name, phone);
accNumber = numAccount++;
balance = 0;// 0 if deposit has to happen after
openOn = new Date();
}
public Date getDate()
{
return openOn;
}
public abstract String toString(); //subclass must implement this method
public class TransactionManager extends javax.swing.JFrame
{
BankDatabase database = new BankDatabase();
TransactionSimulator sim = new TransactionSimulator();
ButtonGroup accType = new ButtonGroup();
private Vector client;
/**
Creates new form TransactionManager
*/
public TransactionManager()
{
initComponents();
database = new BankDatabase();
accType.add(checking);
accType.add(savings);
accType.add(moneyMarket);
cbSpecialSavings.setEnabled(false);
client = new Vector<String>();
}
private void showAllAccountsActionPerformed(java.awt.event.ActionEvent evt)
{
Date openOn = new Date(dateBefore.getText());
outputArea.append(database.showBefore(openOn));
}
About your showBefore() at least make some additional checks
public String showBefore( Date prevDate)
{
StringBuilder builder = new StringBuilder("");
for ( int i = 0; i < size(); i++)
{
Account account = bank[i];
if (account != null) {
Date date = account.getDate();
if (date != null && date.compareTo(prevDate) == -1 ) {
builder.append(account.toString() + "\n")
}
}
}
return builder.toString();
}
and keep in mind what StringBuilder is not synchronized
In other case read more about Java 8 features such as Stream API, New Date/Time API, lambda
public String showBefore(LocalDate prevDate)
{
StringBuilder builder = new StringBuilder("");
Arrays.asList(bank).parallelStream().forEach(account -> {
if (account != null) {
LocalDate date = account.getDate();
if (date != null && date.compareTo(prevDate) == -1 ) {
builder.append(account.toString()).append("\n");
}
}
});
return builder.toString();
}
if(d.month > month)
return -1;
if(d.month > month)
return 1;
You have equivalent if clauses in equals method.

My boolean of an object gets changed without the program doing anything

I've been debugging for hours, and I finally found where the problem is. NOW I have to fix it :)
I thinks something strange happens.
I'm creating an date app, where I calculate which day it is (with leapyear corrections etc).
I have a method, where I take a Year object.
private int totalDays(Year yearnumber) {
System.out.println("Boolean check 1: " + yearnumber.getLeapYear());
//calculate days for whole year//
int daysWholeYear = 0;
for (int i = year.getYearZero(); i < yearnumber.getYear(); i++) {
// here i will add all the days (366) from the leapyears //
if (yearnumber.isLeapYear(i) == true) {
totalDays += year.getLengthyear() + 1;
System.out.println("Boolean check 2: " + yearnumber.getLeapYear());
} else {
totalDays += year.getLengthyear();
}
}
System.out.println("Boolean check 3: " + yearnumber.getLeapYear());
My first two boolean checks are ok.
Code (without the boolean check looped in the for loop)
Boolean check 1: true
Boolean check 2: true
Boolean check 3: false
I need my Boolean in the next lines of my method, where I calculate the days of the months (non whole years). However, my program now thinks that the year is not a leap year and therefore makes wrong calculations.
Because this Boolean changes in my program, the rest of my calculation are off. Can someone explain my why this happens? :)
EDIT: code from my year class:
public class Year {
private static int yearzero = 1753;
private static int lengthYear = 365;
private int year;
private boolean leapYear;
private int startYear; //are used for an interval calculations
private int eindYear; //
public Year(int year) {
this.year = year;
this.leapYear = isLeapYear(year);
}
boolean isLeapYear(int year) {
return leapYear = (year % 400 == 0) ||
((year % 100) != 0 && (year % 4 == 0));
}
public int getYear(){
return year;
}
public int getYearzero () {
return yearZero;
}
public int getLengthYear() {
return lengthYear;
}
public boolean getLeapYear() {
return leapYear;
}
}
Your isLeapYear function sets the object's leapYear variable. This is because the yearnumber.isLeapYear(i) == true will fail, and yearnumber.leapYear will be set to false.
Change
boolean isLeapYear(int year) {
return leapYear = (year % 400 == 0) ||
((year % 100) != 0 && (year % 4 == 0));
}
to:
boolean isLeapYear(int year) {
return ((year % 400 == 0) ||
((year % 100) != 0 && (year % 4 == 0)));
}

Calling toString method from other class's toString. Not reurning values [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
why am i getting the following error message when i call the toString of class Date from toString of class Time2 ?
Exception in thread "main" java.lang.NullPointerException
at Exerciseschpt8.Time2.toString(Time2.java:111)
at Exerciseschpt8.Time2Test.main(Time2Test.java:18)
package Exerciseschpt8;
public class Date{
private int month; // 1-12
private int day; // 1-31 based on month
private int year; // any year
public Date(){
this(0,0,0);
}
public Date(int theMonth, int theDay, int theYear) {
month = checkMonth(theMonth); // validate month
year = theYear; // could validate year
day = checkDay(theDay); // validate day
System.out.printf("Date object constructor for date %s\n", this);
}
private int checkMonth(int month) {
if (month > 0 && month <= 12) // validate month
return month;
else // month is invalid
{
System.out.printf("Invalid month (%d) set to 1.", month);
return 1; // maintain object in consistent state
} // end else
} // end method checkMonth
// utility method to confirm proper day value based on month and year
private int checkDay(int day) {
int[] daysPerMonth = { 0, 31, 28, 31, 30, 31, 30, 28, 31, 30, 31, 30,
31 };
// check if day in range for month
if (day > 0 && day <= daysPerMonth[month])
return day;
// check for leap year
if (month == 2 && day == 29
&& (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)))
return day;
System.out.printf("Invalid day (%d) set to 1.", day);
return 1; // maintain object in consistent state
} // end method checkDay
// return a String of the form month/day/year
public String toString() {
return ""+month+"/"+ day+"/"+year;
} // end method toString
public int nextDay() {
int testDay = day + 1;
if (checkDay(testDay) == testDay)
day = testDay;
else {
day = 1;
//nextMonth();
}
return day;
}
public int nextMonth() {
if (1 == month)
month++;
return month = 1;
}
public String toDateString() {
return month + "/" + day + "*/" + year;
}
}
package Exerciseschpt8;
import Exerciseschpt8.Date;
public class Time2 {
Date dateX;
private int hour; // 0 - 23
private int minute; // 0 - 59
private int second; // 0 - 59
public Time2() {
this(0, 0, 0);
}
public Time2(int h) {
this(h, 0, 0);
}
public Time2(int h, int m) {
this(h, m, 0);
}
public Time2(int h, int m, int s) {
setTime(h, m, s);
}
public Time2(Time2 time) {
this(time.getHour(), time.getMinute(), time.getSecond());
}
public boolean setTime(int h, int m, int s) {
boolean hourValid, minuteValid, secondValid;
hourValid = setHour(h); // set the hour
minuteValid = setMinute(m); // set the minute
secondValid = setSecond(s); // set the second
return (hourValid && minuteValid && secondValid);
}
public boolean setHour(int h) {
// hour = ((h >= 0 && h < 24) ? h : 0);
if (h >= 0 && h < 24) {
hour = h;
return true;
} else {
hour = 0;
return false;
}
} // end method setHour
public boolean setMinute(int m) {
// minute = ((m >= 0 && m < 60) ? m : 0);
if (m >= 0 && m < 60) {
minute = m;
return true;
} else {
minute = 0;
return false;
}
} // end method setMinute
public boolean setSecond(int s) {
// second = ((s >= 0 && s < 60) ? s : 0);
if (s >= 0 && s < 60) {
second = s;
return true;
} else {
second = 0;
return false;
}
} // end method setSecond
public int getHour() {
return hour;
} // end method getHour
public int getMinute() {
return minute;
} // end method getMinute
public int getSecond() {
return second;
} // end method getSecond
// Tick the time by one second
public void tick() {
setSecond(second + 1);
if (second == 23)
incrementMinute();
}
public void incrementMinute() {
setMinute(minute + 1);
if (minute == 25)
incrementHour();
}
public void incrementHour() {
setHour(hour + 1);
if (hour == 0)
dateX.nextDay();
}
public String toString() {
return + hour + ":" + minute + ":" + second + "\n"+dateX.toString();
}
package Exerciseschpt8;
public class Time2Test {
public static void main(String[] args) {
Time2 t1 = new Time2(2,15,23); // 00:00:00
/
Date d1 = new Date(10,23,1973);
//System.out.println(d1.toDateString());
System.out.println("Constructed with:");
System.out.println("t1: all arguments defaulted");
//System.out.printf(" %s\n", t1.toUniversalString());
System.out.printf(" %s\n", t1.toString());
}
}
You are nowhere initializing dateX in your Time2 class and using a method on it (dateX.toString()) in the toString() method of Time2 class. That is causing the valid NullPointerException.
To fix the issue, intialize dateX as appropriate to your program.
In the line Date dateX; you are declaring dateX, but you aren't initializing it, so it's a null pointer. To initialize it, change the line to Date dateX = new Date();

Changing static boolean

I have an assignment for school to make a program which results in either true or false. It's about wether a year is a leap year or not. The problem I have at the moment is that i'm using a public static boolean instead of a public boolean.
This is my code:
public class Assignment {
static boolean isLeapYear;
public static void main(String[] args)
{
int year = 2000;
isLeapYear(year);
}
public static boolean isLeapYear(int year) {
if (((year/100)%4 == 0 && year%4 ==0) || (year % 400 == 0))
isLeapYear = true;
else
isLeapYear = false;
System.out.println(isLeapYear);
return isLeapYear;
}
}
The int year is 2000 at the moment but the rules are like this:
A leap year is a year wich can be divided by 4 unless the year is the beginning of a new century (1700, 1800, 1900.....). So even though you can divide 1900 by 4 you can't divide it by 400 so it's false.
So again the question: What do I need to do so i'm able to use a public boolean instead of a public static boolean?
You would need to create an instance of your class to invoke that method from your main method, if you want to make your method non-static. And then you can make your isLeapYear variable non-static: -
boolean isLeapYear;
public static void main(String[] args)
{
int year = 2000;
new Assigment().isLeapYear(year);
}
public boolean isLeapYear(int year) {
// access isLeapYear as `this.isLeapYear` or just `isLeapYear`
}
But, precisely, you don't need to store your result in a boolean variable. If you want to return a boolean value of some expression, then you can just return that expression.
So, just having this code in your method would also work fine, and it is more readable, and let that method be static: -
return (((year/100)%4 == 0 && year%4 ==0) || (year % 400 == 0))
And from your main call: -
System.out.println("Year : " + year + ", is leap year: " + isLeapYear(year));
You don't need to store this result anywhere.
Use:
public static boolean isLeapYear(int year)
{
return (((year/100)%4 == 0 && year%4 ==0) || (year % 400 == 0));
}
Static methods can only access static variables, only instance methods can access instance methods, which you can infer if you think Object oriented.
Just in case you should store the Boolean isLeapYear
public class Testing {
boolean isLeapYear;
public static void main(String[] args)
{
int year = 2000;
new Testing().isLeapYear(year);
}
public boolean isLeapYear(int year) {
if (((year/100)%4 == 0 && year%4 ==0) || (year % 400 == 0))
isLeapYear = true;
else
isLeapYear = false;
System.out.println(isLeapYear);
return isLeapYear;
}
}
Does your assignment say it has to be stored in a class or instance variable? If not, there is no need for public boolean isLeapYear or public static boolean isLeapYear, just return the result of the calculation and store it in a local variable like this:
public static boolean isLeapYear(int year) {
return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
}
in main method:
int year = 2000;
boolean isLeap = isLeapYear(year);
System.out.println(isLeap);

Categories

Resources