I am building a Date class and when I try to create an object with it doesn't work. (errors in daysPerMonth)
However when I use setNewDay method outside of the object it does work.
Do you guys have any clues on what i'm doing wrong?
Here is my code:
public class Date{
private Dag day;
private Maand month;
private Jaar year;
private int maxday;
public Date(int day, int month, int year){
setDate(day, month, year);
}
public void setDate(int day, int month, int year){
this.month = new Maand(month);
setNewDay(day);
this.year = new Jaar(year);
}
private void daysPerMonth(){
int february;
if(year.getYear()%4 == 0) {
february = 29;
}else{
february = 28;
};
int[] daymonth={31,february,31,30,31,30,31,30,31,30,31,30};
maxday = daymonth[month.getMonth() -1];
}
public void setNewDay(int day){
daysPerMonth();
if(day > 0 && day <= maxday){
this.day = new Dag(day);
} else {
System.out.println("Wrong day");
}
}
}
I see a problem in the order of initialization :
public void setDate(int day, int month, int year){
this.month = new Maand(month);
setNewDay(day); // this method depends indirectly on this.year, which is not yet
// initialized (setNewDay calls daysPerMonth which calls
// year.getYear())
this.year = new Jaar(year);
}
Change it to :
public void setDate(int day, int month, int year){
this.year = new Jaar(year);
this.month = new Maand(month);
setNewDay(day);
}
Looking at the order of your calls, this
public void setDate(int day, int month, int year){
this.month = new Maand(month);
setNewDay(day);
this.year = new Jaar(year);
}
Should be
public void setDate(int day, int month, int year){
this.month = new Maand(month);
this.year = new Jaar(year);
setNewDay(day);
}
Because setNewDay() calls daysPerMonth() and that needs the year (Jaar).
Since you are calling the setNewDay() method before initialising the year ( which is by default null ). And setNewDay() method is instead calling the daysPerMonth() method which uses year but since year is currently null( which is by default value for every reference) You are getting NullPointerException
So you just need to initialise the year before calling the method setNewDay() :
public void setDate(int day, int month, int year){
this.month = new Maand(month);
this.year = new Jaar(year);
setNewDay(day); //call this method after setting up the year
}
So that when you call daysPerMonth() method your year contains valid data :
private void daysPerMonth(){
int february;
if(year.getYear()%4 == 0) { //now year is valid
february = 29;
}else{
february = 28;
}
int[] daymonth={31,february,31,30,31,30,31,30,31,30,31,30};
maxday = daymonth[month.getMonth() -1];
}
Depends on what year you try.
From memory you need three conditions to get February right: Isnot mod 100 & is mod 400
Related
I want to fix the date to month/day/year in my class (Gregorian Calendar) so it works with my tester program. I get errors when running my tester program, I think it has to do with my string toString() method but I have tried to fix it but keep getting errors. I do not understand how having my string output to month + day + year would not work correctly in outputting mmmm/dd/yyyy. Thank you for your help.
Errors:
Exception in thread "main" java.lang.IllegalArgumentException
at Date.<init>(Date.java:15)
at Assign8B.main(Assign8B.java:14)
Class
public class Date {
private int day, month, year;
public Date() {
this.day = 1;
this.month = 1;
this.year = 1970;
}
public Date(int year, int month, int day) {
if (year < 1582) {
throw new IllegalArgumentException();
} else if (month <= 0 && month > 12) {
throw new IllegalArgumentException();
} else if (!isLeapYear(year) && (month == 2 && day == 29)) {
throw new IllegalArgumentException();
} else {
this.day = day;
this.month = month;
this.year = year;
}
}
public void addDays(int days) {
int[] daysOfMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int step = 1;
if(days < 0)
step = -1;
if(isLeapYear(year))
daysOfMonth[1] = 29;
int d = 0;
while(d < days){
d++;
day += step;
if(day > daysOfMonth[month-1]){
day = 1;
month++;
if(month > 12){
year++;
month = 1;
if(isLeapYear(year))
daysOfMonth[1] = 29;
else
daysOfMonth[1] = 28;
}
}
else if(day < 1) {
month--;
if(month == 0) {
month = 12;
year--;
if(isLeapYear(year))
daysOfMonth[1] = 29;
else
daysOfMonth[1] = 28;
}
day = daysOfMonth[month-1];
}
}
}
public void addWeeks(int weeks) {
addDays(weeks * 7);
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public boolean isLeapYear() {
return isLeapYear(this.year);
}
public boolean isLeapYear(int year) {
return(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0));
}
public int daysTo(Date other) {
int days = 0;
int d1, m1, y1, d2, m2, y2;
int sign = 1;
if(this.toString().compareTo(other.toString()) > 0){
d1 = other.day;
m1 = other.month;
y1 = other.year;
d2 = day;
m2 = month;
y2 = year;
sign = -1;
} else {
d1 = day;
m1 = month;
y1 = year;
d2 = other.day;
m2 = other.month;
y2 = other.year;
}
int[] daysOfMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if(isLeapYear(y1))
daysOfMonth[1] = 29;
while(d1 != d2 || m1 != m2 || y1 != y2){
days++;
d1++;
if(d1 > daysOfMonth[m1-1]){
d1 = 1;
m1++;
if(m1 > 12){
y1++;
m1 = 1;
if(isLeapYear(y1))
daysOfMonth[1] = 29;
else
daysOfMonth[1] = 28;
}
}
}
days = days * sign;
return days;
}
public String longDate() {
String[] months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
return months[month-1] + " " + day + ", " + year;
}
public String toString() {
String s = month + "/" + day + "/" + year;
return s;
}
public static int daysTo(Date one, Date two) {
return one.daysTo(two);
}
}
Tester Program
public class Assign8B {
// Part of the main method I'll use to test your class
// NO imports allowed from the JAVA API
public static void main(String[] a) {
Date one = new Date(10,15,1582); // start of Gregorian
Date two = new Date(1,28,2020); // 2020 is a leap year
one.addDays(1); // advance one day (negative subtracts days)
one.addWeeks(10); // advance one week (negative allowed, yes)
System.out.println(two.daysTo(one)); // -159645 days (negative)
System.out.println(one.getDay()); // day is now the 25th (advanced)
System.out.println(one.getMonth()); // returns 12, January is 1
System.out.println(one.getYear()); // still 1582 from start
System.out.println(one.isLeapYear()); // false for 1582
System.out.println(one.toString()); // style is 12/25/1582
try {
Date three = new Date(12,33,1956); // obviously illegal
Date four = new Date(2,29,2013); // illegal leap year
three.setDay(31); // fixes that day of month, OK
four.setMonth(3); // fixes the month, year still wrong
four.setYear(1929); // fixes the year, code not reached
} catch (IllegalArgumentException e) {
System.out.println("Illegal day attempted");
}
// Use UNIX zero of 01/01/70 for default, and create "longDate" output
// I thought a long date was dinner with a person you don't like?
Date five = new Date();
System.out.println(five.longDate()); // January 1, 1970
// Finally, let's understand what static methods are most commonly used for:
System.out.println(Date.daysTo(one, two)); // still 159645 days (positive)
}
}
As #madprogrammer mentioned in the comments, you have to change your Date call because of the order of year month day in your own class constructor, and then look at your add days function and change how you add years in your code.
This question already has answers here:
How to add n days to a Date in java without importing Date/Calendar from java API?
(8 answers)
Closed 3 years ago.
can i use calender by using parameter like if date 5-6-2018 to 26-9-2018
i'm looking for many solve but i didn't get plz i need help for my homework
don't care about 31 or 30 days or Leap Year just i need how to do it
public Date(int day, int month, int year) {
this.day = day;
this.month=month;
this.year=year;
}
public void setDay(int day) {
this.day = day;
}
public void setmonth(int month) {
this.month = month;
}
public void setYear(int year) {
this.year = year;
}
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
public int getYear() {
return year;
}
finally i solved T_T very easy i take 2 weeks for solving
public Date1(int d, int m, int y) {
this.day = d;
this.month = m;
this.year = y;
}
public void addDay() {
month--;
Calendar m = Calendar.getInstance();
m.set(year, month, day);
m.add(day, 5);
java.sql.Date d = new java.sql.Date(m.getTimeInMillis());
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
System.out.println(" date is " + df.format(d));
}
How does the compareTo() method for Dates work here in java? I know that when you compare two dates the result will always be 0 if equal, 1 if the date being
compared inside the compareTo() parameter is older, and -1 if the date inside the parameter is more recent.
//Just an example
String[] da = {"01/14/1975", "08/20/1975", "08/20/1975"};
SimpleDateFormat f = new SimpleDateFormat("MM/dd/yyyy");
Date d1 = new Date();
Date d2 = new Date();
//this outputs 1 because d2 is older than d1
d1 = f.parse(da[1]);
d2 = f.parse(da[0]);
System.out.println(d1.compareTo(d2));
//this outputs 0 because dates are the same
d1 = f.parse(da[1]);
d2 = f.parse(da[2]);
System.out.println(d1.compareTo(d2));
//this outputs -1 because d2 is more recent than d1
d1 = f.parse(da[0]);
d2 = f.parse(da[1]);
System.out.println(d1.compareTo(d2));
Now I want to compare dates without using compareTo() method or any built-in method in java. As much as possible I want to use just the basic operators in java.
What is the computation or the algorithm of the compareTo() method in comparing dates that enable it to return -1, 0, and 1?
Edit:
In the case at the sample problem at my book, using java.util.Date is forbidden, what is supposed to be done is to create your own date object like this:
public class DatesObj
{
protected int day, month, year;
public DatesObj (int mm, int dd, int yyyy) {
month = mm;
day = dd;
year = yyyy;
}
public int getMonth() { return month; }
public int getDay() { return day; }
public int getYear() { return year; }
}
Now how do I compare this as if like they're int and determine which is old and which is newer??
If you want to compare two dates just as if they were just plain-old integers, you must first turn each date into a plain-old integer. The easiest way to turn a year/month/day representation of a date into a plain-old integer, that can be effectively compared with plain-old integers from other dates, is to line the pieces up in exactly that order: year first, month next, day last:
// in DateObj class....
public int getDateInt() {
return (yyyy * 10000) + (mm * 100) + dd;
}
So for March 19, 2019, you get 20190319, and for December 7, 1941 you get 19411207; by comparing the "integerized" versions of the dates you can see that:
19411207 < 20190319, just as December 7, 1941 is earlier than March 19, 2019;
20190319 > 19411207, just as March 19, 2019 is later than December 7, 1941;
19411207 != 20190319, just as December 7, 1941 and March 19, 2019 are different dates
You're limited to dates within the Common Era and no more than about 200,000 years into the future with this particular implementation. But with a little tweaking, you could easily easily handle dates outside these ranges, an exercise that I will, as the textbooks so often say, leave as an exercise for the reader.
Implement Comparable and override compareTo().
class DatesObj implements Comparable<DatesObj>{
protected int day, month, year;
public DatesObj(int mm, int dd, int yyyy) {
month = mm;
day = dd;
year = yyyy;
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
public int getYear() { return year; }
#Override
public int compareTo(DatesObj o) {
int diff = this.year - o.year;
if(diff != 0) {
return diff;
}
diff = this.month - o.month;
if(diff != 0) {
return diff;
}
return this.day - o.day;
}
}
Compare the years. If the years of both the dates are same, compare the months.
If the months are same, compare the dates.
public int compareDate(DatesObj d) {
if (this.year != d.year) {
if (this.year > d.year)
return 1;
else
return -1;
}
if (this.month != d.month) {
if (this.month > d.month)
return 1;
else
return -1;
}
if (this.day != d.day) {
if (this.day > d.day)
return 1;
else
return -1;
}
return 0;
}
Ref : https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html
Ref : https://developer.android.com/reference/java/util/Calendar
create own class with Interface Comparable
class DateCompare implements Comparable<Date>
{
protected int day, month, year;
public DateCompare(int mm, int dd, int yyyy) {
month = mm;
day = dd;
year = yyyy;
}
#Override
public int compareTo(Date o) {
Calendar cal = Calendar.getInstance();
cal.setTime(o);
int diff = this.year - cal.get(Calendar.YEAR);
if(diff != 0) {
return diff;
}
diff = this.month - cal.get(Calendar.MONTH);
if(diff != 0) {
return diff;
}
return this.day - cal.get(Calendar.DAY_OF_MONTH);
}
public int getMonth() {
return month;
}
public int getDay() {
return day;
}
public int getYear() { return year; }
}
And Other More Helpful
https://gist.github.com/Ashusolanki/fed3b6a680092985ac0ab93ed70fcd7c
private String postTime(Date date)
{
long postTime = date.getTime();
long atTime = System.currentTimeMillis();
long diff = atTime - postTime;
long sec = TimeUnit.SECONDS.convert(diff, TimeUnit.MILLISECONDS);
if (sec >= 60) {
long minit = TimeUnit.MINUTES.convert(diff, TimeUnit.MILLISECONDS);
if (minit >= 60) {
long hours = TimeUnit.HOURS.convert(diff, TimeUnit.MILLISECONDS);
if (hours >= 24) {
long days = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
return days + " Days Ago";
} else {
return hours + " Hours Ago";
}
} else {
return minit + " Minutes Ago";
}
} else {
return sec + " Secounds Ago";
}
}
I am quite new with JUnit testing and my background in Java programming is not solid. I need an expert to help me make my test run correctly. I would like you to focus on my parameters, but if there is any better suggestion I am willing to try it. I need to make test run for ordinalDate() only, thanks.
DateUtilityTest.java
package week4;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
#RunWith(Parameterized.class)
public class DateUtilityTest {
DateUtility date = new DateUtility();
private int input;
private static int month;
private static int day;
private static int year;
public DateUtilityTest(int input, int month, int day, int year) {
super();
this.input = input;
DateUtilityTest.month = month;
DateUtilityTest.day = day;
DateUtilityTest.year = year;
}
#Parameters
public static Collection<Object[]> <Integer> List<java.lang.Integer> testConditions() {
Object input[][] = {
{3, 16, 1993},
{6, 24, 1997},
{9, 8, 1995}
};
return Arrays.asList(month, day, year);
}
#Test
public void test() {
assertEquals(input ,DateUtility.ordinalDate(month, day, year));
}
}
DateUtility.java
package week4;
public class DateUtility {
//Returns whether year is a leap year?
public static boolean isLeapYear (int year)
{return (year%4 == 0 && year%100 != 0) || year%400 == 0;}
//Returns the number of days in month (in year)
public static int daysIn (int month, int year) throws IllegalArgumentException
{
if (year < 1)
throw new IllegalArgumentException("daysIn: year ("+year+") not positive");
if (month < JANUARY || month > DECEMBER)
throw new IllegalArgumentException("daysIn: month ("+month+") not in range [1,12]");
//Thirty days hath September, April, June and November...
if (month == APRIL ||
month == JUNE ||
month == SEPTEMBER ||
month == NOVEMBER)
return 30;
//...all the rest have thirty one...
else if (month == JANUARY ||
month == MARCH ||
month == MAY ||
month == JULY ||
month == AUGUST ||
month == OCTOBER ||
month == DECEMBER)
return 31;
//...except February (must be FEBRUARY in else: see possible exception)
else
return 28 + (isLeapYear(year) ? 1 : 0);
}
//Returns the ordinal (1st, 2nd, 3rd, etc) representing month, day, year
public static int ordinalDate (int month, int day, int year)
{
int ordinal = 0;
//Scan every earlier month, summing the # of days in that month...
for (int m=JANUARY; m < month; m++)
ordinal += daysIn(m, year);
//...and add day in the current month
return ordinal + day;
}
//Returns a date as an American or European String
public static String americanFormat (int month, int day, int year)
{return month + "/" + day + "/" + year;}
public static String europeanFormat (int month, int day, int year)
{return day + "/" + month + "/" + year;}
//Fields: all public static final (constants supplied by class)
//These could be private, for use only in this class,
// but what the heck, let programmers use them from this class
// (as constants, there is nothing a programmer can do to mess things up)
public static final int JANUARY = 1;
public static final int FEBRUARY = 2;
public static final int MARCH = 3;
public static final int APRIL = 4;
public static final int MAY = 5;
public static final int JUNE = 6;
public static final int JULY = 7;
public static final int AUGUST = 8;
public static final int SEPTEMBER = 9;
public static final int OCTOBER = 10;
public static final int NOVEMBER = 11;
public static final int DECEMBER = 12;
}
Each of the entries of your list of parameters is an array with only 3 numbers
Object input[][] = {
{3, 16, 1993},
{6, 24, 1997},
{9, 8, 1995}
};
while the constructor of your test class expects 4 parameter.
public DateUtilityTest(int input, int month, int day, int year)
I think the value for input is missing. Therefore the test does not run.
What I'm trying to do is access an object, in this case date1 which has 3 attributes day, month and year. I'm attempting to make a method called showTomorrow() which will display the objects information 1 day infront in String format. This means I cannot alter the attributes of the original object.
I've written the Data.java program and it's shown below, if someone could point me in the right direction or show me what it would be really helpfull.
This is what I'd essentially be running on my main method I believe.
**Date date1 = new Date(30, 12, 2013)** // instantiate a new object with those paramaters
**date1.showDate();** // display the original date
**date1.tomorrow();** // shows what that date would be 1 day infront
The problem is right now it's not displaying anything. I thought that by saying dayTomorrow = this.day++; I was adding it's default value + 1 day to the variable dayTomorrow.
public class Date
{
private int day;
private int month;
private int year;
private int dayTomorrow;
private int monthTomorrow;
private int yearTomorrow;
public Date()
{
day = 1;
month = 1;
year = 1970;
}
public Date(int inDay, int inMonth, int inYear)
{
day = inDay;
month = inMonth;
year = inYear;
}
public void setDate(int inDay, int inMonth, int inYear)
{
day = inDay;
month = inMonth;
year = inYear;
}
public String getDate()
{
String strDate;
strDate = day + "/" + month + "/" + year;
return strDate;
}
public String getTomorrow()
{
String strTomorrow;
strTomorrow = dayTomorrow + "/" + monthTomorrow + "/" + yearTomorrow;
return strTomorrow;
}
public String tomorrow()
{
dayTomorrow = this.day++;
monthTomorrow = this.month;
yearTomorrow = this.year;
if(dayTomorrow > 30)
{
dayTomorrow = 1;
monthTomorrow = this.month++;
}
if(monthTomorrow > 12)
{
monthTomorrow = 1;
yearTomorrow = this.year++;
}
return getTomorrow();
}
public void showDate()
{
System.out.print("\n\n THIS OBJECT IS STORING ");
System.out.print(getDate());
System.out.print("\n\n");
}
public void showTomorrow()
{
System.out.print("\n\n THE DATE TOMORROW IS ");
System.out.print(getTomorrow());
System.out.print("\n\n");
}
public boolean equals(Date inDate)
{
if(this.day == inDate.day && this.month == inDate.month && this.year == inDate.year)
{
return true;
}
else
{
return false;
}
}
}
You just need to use ++this.day, ++this.month and ++this.year. When you use this.day++ it returns the previous date value, not the new. Putting the ++ in the front solves the problem. Also, it changes the day value... you might want to change that to this.day + 1.
Are You calling showDate() after date1.tomorrow() to show your output?
or instead of date1.tomorrow(); call date1.showTomorrow();
Have a look at this : http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op1.html
post incremention ...
You could use the native date support in java but I figured you are just practicing right?
This should do the trick:
public class Date {
private int day = 1;
private int month = 1;
private int year = 1970;
private int dayTomorrow = day+1;
private int monthTomorrow;
private int yearTomorrow;
public Date()
{
tomorrow();
}
public Date(int inDay, int inMonth, int inYear)
{
day = inDay;
month = inMonth;
year = inYear;
tomorrow();
}
public void setDate(int inDay, int inMonth, int inYear)
{
day = inDay;
month = inMonth;
year = inYear;
}
public String getDate()
{
String strDate;
strDate = day + "/" + month + "/" + year;
return strDate;
}
public String getTomorrow()
{
String strTomorrow;
strTomorrow = dayTomorrow + "/" + monthTomorrow + "/" + yearTomorrow;
return strTomorrow;
}
public void tomorrow()
{
monthTomorrow = this.month;
yearTomorrow = this.year;
if(dayTomorrow > 30)
{
dayTomorrow = 1;
monthTomorrow = this.month++;
}
if(monthTomorrow > 12)
{
monthTomorrow = 1;
yearTomorrow = this.year++;
}
}
public void showDate()
{
System.out.print("\n\n THIS OBJECT IS STORING ");
System.out.print(getDate());
System.out.print("\n\n");
}
public void showTomorrow()
{
System.out.print("\n\n THE DATE TOMORROW IS ");
System.out.print(getTomorrow());
System.out.print("\n\n");
}
public boolean equals(Date inDate)
{
if(this.day == inDate.day && this.month == inDate.month && this.year == inDate.year)
{
return true;
}
else
{
return false;
}
}
}
Look carefully for any changes i've made ;)
Here's the main:
public static void main(String[] args) {
Date d = new Date();
d.showDate();
d.showTomorrow();
}