Confusion about java dates comparison - java

Pre-notes:
Yes, this is homework.
Our school's tutor is out for the day
My book is useless
I'm not exactly sure what to search for on google for help with my confusion...
Question:
Anyway - The question / confusion that I have involves the first bit of code that I have in my program to test the compareTo method.
Would I use the variables at the top of the code as my variables in the static void main area, or assign new variables, like I do have?
The values in public Date()... <-- Is that the date that my code in static void main is comparing to? (If so, I have a piece of code that I want to use that uses the current date, rather than what's in Date()).
I may have more questions later on, but I hope that someone can clear up my confusion better than my book or google has proven thus far.
Code:
package date;
import java.util.*;
public class Date implements Comparable
{
static Scanner console = new Scanner(System.in);
private int dMonth; //Part a of confusion 1
private int dDay;
private int dYear;
public Date()
{
dMonth = 1; //Confusion 2
dDay = 1;
dYear = 1900;
}
public Date(int month, int day, int year)
{
dMonth = month;
dDay = day;
dYear = year;
}
public void setDate(int month, int day, int year)
{
dMonth = month;
dDay = day;
dYear = year;
}
public int getMonth()
{
return dMonth;
}
public int getDay()
{
return dDay;
}
public int getYear()
{
return dYear;
}
public String toString()
{
return (dMonth + "." + dDay + "." + dYear);
}
public boolean equals(Object otherDate)
{
Date temp = (Date) otherDate;
return (dYear == temp.dYear
&& dMonth == temp.dMonth
&& dDay == temp.dDay);
}
public int compareTo(Object otherDate)
{
Date temp = (Date) otherDate;
int yrDiff = dYear - temp.dYear;
if (yrDiff !=0)
return yrDiff;
int monthDiff = dMonth - temp.dMonth;
if (monthDiff !=0)
return monthDiff;
return dDay - temp.dDay;
}
public static void main(String[] args) //Part b of confusion 1
{
int month;
int day;
int year;
Date temp;
System.out.print("Enter date in the form of month day year");
month = console.nextInt();
day = console.nextInt();
year = console.nextInt();
System.out.println();
}
}

As mentioned in the comments, I think you need to read about the difference between static methods/attributes and the ones in instances. I think this is what you should be doing in the main method:
System.out.print("Enter date in the form of month day year");
Date date1 = new Date(console.nextInt(), console.nextInt(), console.nextInt());
System.out.print("Enter second date in the form of month day year");
Date date2 = new Date(console.nextInt(), console.nextInt(), console.nextInt());
System.out.println("Comparison result:");
System.out.println(date1.compareTo(date2));
Regarding your confusion points:
Class attributes
private int dMonth; //Part a of confusion 1
private int dDay;
private int dYear;
These are special variables. Each instance (that is, every object created with new Date) has its own value for dMonth, dDay and dYear. It is not accessible from the main because main is a static method, and thus doesn't have access to instance variables.
If you didn't understand, at least you know the names to search further.
Default constructor
public Date()
{
dMonth = 1; //Confusion 2
dDay = 1;
dYear = 1900;
}
Those values are used when you create a new Date object without specifying which month/day/year you want. So new Date(2, 3, 2013) means 2/3/2013, while new Date() means 1/1/1900.

No you can't, dMonth, dDay and dYear are member variables. If you want to use them directly inside your main method you will have to use the keyword static so that they become class variables. But no, that is not what you want.
Your main method is doing nothing useful really. Your confusion point 2 is a constructor:
Date d = new Date(); // Data Instance -> First constructor
d.getMonth(); // 1
d.getDay(); // 1
d.getYear(); // 1900
Date d2 = new Date(2, 2, 1901);
d2.getMonth(); // 2
d2.getDay(); // 2
d2.getYear(); // 1901
d2.setDate(3, 3, 1902);
d2.getMonth(); // 3
d2.getDay(); // 3
d2.getYear(); // 1902
d.getMonth(); // Still 1 since member variables of d are independent of d2
d.compareTo(d2); // -2 -> (1900 - 1902)
You can create date instances inside your main method and use code like the one above to access member variables (probably the whole point of your exercise).

Related

Java Array of Objects How to Access and Print

I am entering data into two classes (Date and Task) that are array of objects (I believe that is what they are officially called) and part of a Day class. I can add data to the Task class using the setter and I can add data to the Date class using the setter. The question I have is how do I access that data entered into the Date and Task classes through the Day class that contains those objects. I am using the Tester class to enter the data into these classes. I can access and print the data for each date/task(s) combo right after I add the data to the classes by using the "System.out.println(day1);". However, I can only print the last data I entered into the classes. When I try to access the objects' data through the Day class, it is not showing anything.
I would expect my results to be the following:
2022/2/23
Description: Write code Hours: 2.5
Description: Research Hours: 1.5
For a total of 4.0 hours.
2022/2/24
Description: Read code Hours: 5.0
For a total of 5.0 hours.
But instead I just get the following error when I try to compile it using JGrasp:
Tester.java:28: error: cannot find symbol
for (i=0; i < day1.length; i++) {
^
symbol: variable length
location: variable day1 of type Day
Tester.java:29: error: incompatible types: String cannot be converted to Task[]
array = day1.getDate();
^
2 errors
How do I print out/access the objects in the Day class? I'm confused about how to do this in this context. When I use "System.out.println(day1);" I was assuming it would print out both of the sets of data I entered into the classes, but only the most recent one printed. I can print off the first data set entered by putting "System.out.println(day1);" after the first data set, but that is the only way it will print. It almost seems like I am writing over the top of the first set of data I add with the second set of data. Add to that I'm pretty unsure about how objects embedded within objects work. Thanks for your help! Here is the code:
public class Day implements Comparable {
public static final int MAX=50;
private Task[] tasks;
private int numTasks;
Date myDate;
Day myDay;
public Day(int year, int month, int day) {
myDate = new Date(year, month, day);
tasks = new Task[MAX];
numTasks = 0;
}
public void addTask(Task newTask) {
tasks[numTasks] = newTask;
numTasks++;
}
public int getNumTasks() {
return numTasks;
}
public String getDate() {
return myDate.toString();
}
public double getTotalHours() {
int i;
double sum;
sum = 0;
for (i=0; i < numTasks; i++)
sum += tasks[i].getHours();
return sum;
}
public String toString() {
String result;
int i;
result = myDate.toString()+"\n";
for (i=0; i < numTasks; i++)
result += tasks[i].toString()+"\n";
result += "For a total of "+getTotalHours()+" hours.";
return result;
}
//other getters and setters in this class too
}
public class Date implements Comparable {
private int year, month, day;
public Date (int inYear, int inMonth, int inDay) {
year = inYear;
month = inMonth;
day = inDay;
if (day > getNumDaysMonth(month, year) ||
month < 1 || month > 12) {
year = -1;
month = -1;
day = -1;
}
//other getters and setters below this
}
}
public class Task implements Comparable{
// field variables
private String description;
private double hours;
// constructors -> initialize all field variables - specialized method
public Task(String desc, double hrs) {
description = desc;
hours = hrs;
}
//other getters and setters below this
}
import java.util.Arrays;
public class Tester {
public static void main(String[] args) {
Day day1;
Task task1;
Task array[];
Day array2[];
double totalHours;
int n, i;
day1 = new Day(2022, 2, 23);
task1 = new Task("Write code", 2.5);
day1.addTask(task1);
task1 = new Task("Research", 1.5);
day1.addTask(task1);
n = day1.getNumTasks();
System.out.println("Number of tasks = "+n);
day1 = new Day(2022, 2, 24);
task1 = new Task("Read code", 5.0);
day1.addTask(task1);
System.out.println(day1);
System.out.println();
for (i=0; i < day1.length; i++) {
array = day1.getDate();
System.out.println(array);
}
totalHours = day1.getTotalHours();
System.out.println("Total hours = "+totalHours);
}
}
You're assigning "day1.getDate()", which is a String, to "array", which is a task array. These are not compatible. All you need to do is System.out.println(day1.getDate()); That would only print the same date day1.length times though. I suppose you want something from the day1 tasks. You probably want to implement a Task Day.getTask(int index) method to access them. It would be bad practice to return the whole task array, since the caller could then modify it. If you did want to implement a Task[] Day.getTasks() method, it should return a copy of the task array.

For the program mentioned above I am getting runtime error for one test case. All the remaining test cases are passed. Any suggestions

class Result {
public static String findDay(int month, int day, int year) {
String [] B = {"MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"};
Calendar A = Calendar.getInstance();
A.set(Calendar.MONTH, month-1);
A.set(Calendar.YEAR, year);
A.set(Calendar.DAY_OF_MONTH,day);
return B[A.get(Calendar.DAY_OF_WEEK)-2];
}
}
I am getting run time error for the code mentioned above for one of the test cases. I don't understand why, can you please explain me how to resolve this kind of run time errors in the future.
I see 2 problems in this code, the both are about indexes.
I propose this version :
public static String findDay(int month, int day, int year) {
String [] B = {"MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"};
Calendar A = Calendar.getInstance();
final int monthIndex = (month + 11) % 12;
A.set(Calendar.MONTH, monthIndex);
A.set(Calendar.YEAR, year);
A.set(Calendar.DAY_OF_MONTH,day);
final int dayIndex = (A.get(Calendar.DAY_OF_WEEK) + 5) % 7;
return B[dayIndex];
}
As you can see, I use the modulo to still in indexes range of your Array "B". I do the same for the "month index".

Beginner Java: How do I write a constructor to call methods?

I am trying to figure out how to write a constructor that calls methods. I have been given the following instructions for a Java project. The emboldened ones are relevant to this step. Step 3 I have completed, but I can't confirm if I completed it correctly. The code for Step 3 is the second Date constructor within the Date class.
Uncomment line 1 from DateTest (don’t forget to delete the “Line 1.” part) and build and run the project. What is the output? Why is this the output?
Create a default constructor for Date which sets the date to 1/1/2000. Build and run the project. What is the output?
Create a constructor that has three int parameters for the month, day, and year and sets the values of these instance variables to the values passed in. Uncomment lines 2 and 3. Build and run the project. What is the output?
Rewrite the constructor from question 3 so that it calls setMonth(), setDay(), and setYear(). Build and run the project. What is the output?
Write a set() method that has three parameters for the month, day, and year. Uncomment lines 4 and 5. Build and run the project. What is the output?
Rewrite the constructor from question 3 so that it calls set (). Build and run the project. What is the output?
Below is the code for Date class and DateTest class.
package datetest;
import java.util.Scanner;
public class Date
{
public Date() {
month = 1;
day = 1;
year = 2000;
}
public Date(int m, int d, int y) {
month = m;
day = d;
year = y;
}
private int month;
private int day;
private int year; //a four digit number.
public void setYear(int newYear)
{
year = newYear;
}
public void setMonth(int newMonth)
{
if ((newMonth <= 0) || (newMonth > 12))
{
month=newMonth;
}
else
month = newMonth;
}
public void setDay(int newDay)
{
if ((newDay <= 0) || (newDay > 31))
{
day=1;
}
else
day = newDay;
}
public int getMonth( )
{
return month;
}
public int getDay( )
{
return day;
}
public int getYear( )
{
return year;
}
public void printDate( )
{
System.out.print(getMonth() + "/" + getDay() + "/" + getYear());
}
public void readInput( )
{
boolean tryAgain = true;
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter month, day, and year.");
System.out.println("Do not use a comma.");
month = keyboard.nextInt( );
day = keyboard.nextInt( );
year = keyboard.nextInt( );
}
}
This is the DateTest class.
package datetest;
public class DateTest {
public static void main(String[] args) {
Date today = new Date();
System.out.println("Today’s date is " + today.getMonth() + "/" + today.getDay() + "/" + today.getYear());
//Line 2. today = new Date(55, 55, 2011);
//Line 3. System.out.println("Today’s date is " + today.getMonth() + "/" + today.getDay() + "/" + today.getYear());
//Line 4. today.set(10, 5, 2011);
//Line 5. System.out.println("Today’s date is " + today.getMonth() + "/" + today.getDay() + "/" + today.getYear());
}
}
I have attempted to write the code to call the methods in step 4. Would the following code be the correct way to write a constructor to call methods?
public Date (int m, int d, int y) {
this.setMonth(month);
this.setDay(day);
this.setYear(year);
}
Would the following code be the correct way to write a constructor to call methods?
public Date (int m, int d, int y) {
this.setMonth(month);
this.setDay(day);
this.setYear(year);
}
Yes, if you used your m, d, and y arguments instead of month, day, and year:
public Date (int m, int d, int y) {
this.setMonth(m);
this.setDay(d);
this.setYear(y);
}
With your code, you're actually just setting the instance members (month and so on) to their existing values (because month in the constructor is automatically resolved to the instance data member month using an implied this.). So I'm guessing when you tried it, you ended up with zeroes and didn't understand why. (int members are auto-initialized to zero before the code in the constructor runs.)

Compare two objects, and return string. But one object doesn't take parameters?

This is homework.
GOAL: I want to compare the date of two objects to decide whether my person object is an adult or not and store this in a string.
The strange thing is, all my values of date d1 are 0;
public class Date {
public int day, month, year;
public String child
Date(date d1, date d2) {
if ((d1.year - d2.year > 18) ||
((d1.year - d2.year == 18) && (d2.year> d1.year)) ||
((d1.year - d2.year == 18) && (d2.year == d1.maand) && (d2.day > d1.day))) {
child = adult;
} else {
child = child;
}
Date(int a, int b, int c) {
a = year;
b = month;
c = day;
}
Date (String birthdate) {
String pattern = "\\d{2}-\\d{2}-\\d{4}";
boolean b = birthdate.matches(pattern);
if (b) {
String[] str = birthdate.split("-");
for (String s: str)
this.day = Integer.parseInt(str[0]);
this.month = Integer.parseInt(str[1]);
this.year = Integer.parseInt(str[2]);
this.child = false;
} else {
System.out.println("Wrong format");
}
}
When I make a test, this happens:
System.out.println("D1 year = " + d1.year);
System.out.println("D1 day = " + d1.day);
System.out.println("D1 month = " + d1.month);
Result:
D1 year = 0
D1 day = 0
D1 month = 0
Why does this happen? Lets look at my other class.
My other class, where my method infoPerson is located is as following:
public static Person infoPerson() {
String name, lastname, birthdate;
Datum birthday, today;
System.out.println("Firstname:");
name = userInput();
System.out.println("Lastname:");
lastname = userInput();
System.out.println("Birthdate?:");
birthdate = userInput();
//here I send the string birthdate to my Date class
birthday = new Date(birthdate);
today = new Date(3, 7, 2013);
//Here I want to compare my two Date objects, today and birthday. This is were I got stuck, how do I do this correctly?
dateChild = new Date(today, birthday);
// here i send the new date to my Person class what consists of two strings and Data birthday
return new Gast(name, lastname, dateChild);
}
The assignment in the constructor is reversed:
Date(int a, int b, int c) {
a = year; // should be year = a;
b = month; // month = b;
c = day; // day = c;
}
Please don't use the class name same as the one defined in Java API. Date is already a class in java.util package.
Apart from that there are many compiler errors in your code:
public string child - isn't going to compile. Should be String not string.
void compareTo(date d1, date d2) - I don't know what you're trying to do here. But this too won't compile. Undefined type - date
You've declared the Datum birthday and initializing it using new Date(...). That too wouldn't work.
For some reason, I feel like you don't have any method in your class, but just a bunch of constructors. My suggestion would be - throw that code away, and start afresh.
And please don't use a bunch of integer fields to store birthdays. Use a Calendar instance instead.

How do I calculate someone's age in Java?

I want to return an age in years as an int in a Java method.
What I have now is the following where getBirthDate() returns a Date object (with the birth date ;-)):
public int getAge() {
long ageInMillis = new Date().getTime() - getBirthDate().getTime();
Date age = new Date(ageInMillis);
return age.getYear();
}
But since getYear() is deprecated I'm wondering if there is a better way to do this? I'm not even sure this works correctly, since I have no unit tests in place (yet).
JDK 8 makes this easy and elegant:
public class AgeCalculator {
public static int calculateAge(LocalDate birthDate, LocalDate currentDate) {
if ((birthDate != null) && (currentDate != null)) {
return Period.between(birthDate, currentDate).getYears();
} else {
return 0;
}
}
}
A JUnit test to demonstrate its use:
public class AgeCalculatorTest {
#Test
public void testCalculateAge_Success() {
// setup
LocalDate birthDate = LocalDate.of(1961, 5, 17);
// exercise
int actual = AgeCalculator.calculateAge(birthDate, LocalDate.of(2016, 7, 12));
// assert
Assert.assertEquals(55, actual);
}
}
Everyone should be using JDK 8 by now. All earlier versions have passed the end of their support lives.
Check out Joda, which simplifies date/time calculations (Joda is also the basis of the new standard Java date/time apis, so you'll be learning a soon-to-be-standard API).
e.g.
LocalDate birthdate = new LocalDate (1970, 1, 20);
LocalDate now = new LocalDate();
Years age = Years.yearsBetween(birthdate, now);
which is as simple as you could want. The pre-Java 8 stuff is (as you've identified) somewhat unintuitive.
EDIT: Java 8 has something very similar and is worth checking out.
EDIT: This answer pre-dates the Java 8 date/time classes and is not current any more.
Modern answer and overview
a) Java-8 (java.time-package)
LocalDate start = LocalDate.of(1996, 2, 29);
LocalDate end = LocalDate.of(2014, 2, 28); // use for age-calculation: LocalDate.now()
long years = ChronoUnit.YEARS.between(start, end);
System.out.println(years); // 17
Note that the expression LocalDate.now() is implicitly related to the system timezone (which is often overlooked by users). For clarity it is generally better to use the overloaded method now(ZoneId.of("Europe/Paris")) specifying an explicit timezone (here "Europe/Paris" as example). If the system timezone is requested then my personal preference is to write LocalDate.now(ZoneId.systemDefault()) to make the relation to the system timezone clearer. This is more writing effort but makes reading easier.
b) Joda-Time
Please note that the proposed and accepted Joda-Time-solution yields a different computation result for the dates shown above (a rare case), namely:
LocalDate birthdate = new LocalDate(1996, 2, 29);
LocalDate now = new LocalDate(2014, 2, 28); // test, in real world without args
Years age = Years.yearsBetween(birthdate, now);
System.out.println(age.getYears()); // 18
I consider this as a small bug but the Joda-team has a different view on this weird behaviour and does not want to fix it (weird because the day-of-month of end date is smaller than of start date so the year should be one less). See also this closed issue.
c) java.util.Calendar etc.
For comparison see the various other answers. I would not recommend using these outdated classes at all because the resulting code is still errorprone in some exotic cases and/or way too complex considering the fact that the original question sounds so simple. In year 2015 we have really better libraries.
d) About Date4J:
The proposed solution is simple but will sometimes fail in case of leap years. Just evaluating the day of year is not reliable.
e) My own library Time4J:
This works similar to Java-8-solution. Just replace LocalDate by PlainDate and ChronoUnit.YEARS by CalendarUnit.YEARS. However, getting "today" requires an explicit timezone reference.
PlainDate start = PlainDate.of(1996, 2, 29);
PlainDate end = PlainDate.of(2014, 2, 28);
// use for age-calculation (today):
// => end = SystemClock.inZonalView(EUROPE.PARIS).today();
// or in system timezone: end = SystemClock.inLocalView().today();
long years = CalendarUnit.YEARS.between(start, end);
System.out.println(years); // 17
Calendar now = Calendar.getInstance();
Calendar dob = Calendar.getInstance();
dob.setTime(...);
if (dob.after(now)) {
throw new IllegalArgumentException("Can't be born in the future");
}
int year1 = now.get(Calendar.YEAR);
int year2 = dob.get(Calendar.YEAR);
int age = year1 - year2;
int month1 = now.get(Calendar.MONTH);
int month2 = dob.get(Calendar.MONTH);
if (month2 > month1) {
age--;
} else if (month1 == month2) {
int day1 = now.get(Calendar.DAY_OF_MONTH);
int day2 = dob.get(Calendar.DAY_OF_MONTH);
if (day2 > day1) {
age--;
}
}
// age is now correct
/**
* This Method is unit tested properly for very different cases ,
* taking care of Leap Year days difference in a year,
* and date cases month and Year boundary cases (12/31/1980, 01/01/1980 etc)
**/
public static int getAge(Date dateOfBirth) {
Calendar today = Calendar.getInstance();
Calendar birthDate = Calendar.getInstance();
int age = 0;
birthDate.setTime(dateOfBirth);
if (birthDate.after(today)) {
throw new IllegalArgumentException("Can't be born in the future");
}
age = today.get(Calendar.YEAR) - birthDate.get(Calendar.YEAR);
// If birth date is greater than todays date (after 2 days adjustment of leap year) then decrement age one year
if ( (birthDate.get(Calendar.DAY_OF_YEAR) - today.get(Calendar.DAY_OF_YEAR) > 3) ||
(birthDate.get(Calendar.MONTH) > today.get(Calendar.MONTH ))){
age--;
// If birth date and todays date are of same month and birth day of month is greater than todays day of month then decrement age
}else if ((birthDate.get(Calendar.MONTH) == today.get(Calendar.MONTH )) &&
(birthDate.get(Calendar.DAY_OF_MONTH) > today.get(Calendar.DAY_OF_MONTH ))){
age--;
}
return age;
}
I simply use the milliseconds in a year constant value to my advantage:
Date now = new Date();
long timeBetween = now.getTime() - age.getTime();
double yearsBetween = timeBetween / 3.15576e+10;
int age = (int) Math.floor(yearsBetween);
If you are using GWT you will be limited to using java.util.Date, here is a method that takes the date as integers, but still uses java.util.Date:
public int getAge(int year, int month, int day) {
Date now = new Date();
int nowMonth = now.getMonth()+1;
int nowYear = now.getYear()+1900;
int result = nowYear - year;
if (month > nowMonth) {
result--;
}
else if (month == nowMonth) {
int nowDay = now.getDate();
if (day > nowDay) {
result--;
}
}
return result;
}
It's perhaps surprising to note that you don't need to know how many days or months there are in a year or how many days are in those months, likewise, you don't need to know about leap years, leap seconds, or any of that stuff using this simple, 100% accurate method:
public static int age(Date birthday, Date date) {
DateFormat formatter = new SimpleDateFormat("yyyyMMdd");
int d1 = Integer.parseInt(formatter.format(birthday));
int d2 = Integer.parseInt(formatter.format(date));
int age = (d2-d1)/10000;
return age;
}
With the date4j library :
int age = today.getYear() - birthdate.getYear();
if(today.getDayOfYear() < birthdate.getDayOfYear()){
age = age - 1;
}
This is an improved version of the one above... considering that you want age to be an 'int'. because sometimes you don't want to fill your program with a bunch of libraries.
public int getAge(Date dateOfBirth) {
int age = 0;
Calendar born = Calendar.getInstance();
Calendar now = Calendar.getInstance();
if(dateOfBirth!= null) {
now.setTime(new Date());
born.setTime(dateOfBirth);
if(born.after(now)) {
throw new IllegalArgumentException("Can't be born in the future");
}
age = now.get(Calendar.YEAR) - born.get(Calendar.YEAR);
if(now.get(Calendar.DAY_OF_YEAR) < born.get(Calendar.DAY_OF_YEAR)) {
age-=1;
}
}
return age;
}
The correct answer using JodaTime is:
public int getAge() {
Years years = Years.yearsBetween(new LocalDate(getBirthDate()), new LocalDate());
return years.getYears();
}
You could even shorten it into one line if you like. I copied the idea from BrianAgnew's answer, but I believe this is more correct as you see from the comments there (and it answers the question exactly).
Try to copy this one in your code, then use the method to get the age.
public static int getAge(Date birthday)
{
GregorianCalendar today = new GregorianCalendar();
GregorianCalendar bday = new GregorianCalendar();
GregorianCalendar bdayThisYear = new GregorianCalendar();
bday.setTime(birthday);
bdayThisYear.setTime(birthday);
bdayThisYear.set(Calendar.YEAR, today.get(Calendar.YEAR));
int age = today.get(Calendar.YEAR) - bday.get(Calendar.YEAR);
if(today.getTimeInMillis() < bdayThisYear.getTimeInMillis())
age--;
return age;
}
I use this piece of code for age calculation ,Hope this helps ..no libraries used
private static DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
public static int calculateAge(String date) {
int age = 0;
try {
Date date1 = dateFormat.parse(date);
Calendar now = Calendar.getInstance();
Calendar dob = Calendar.getInstance();
dob.setTime(date1);
if (dob.after(now)) {
throw new IllegalArgumentException("Can't be born in the future");
}
int year1 = now.get(Calendar.YEAR);
int year2 = dob.get(Calendar.YEAR);
age = year1 - year2;
int month1 = now.get(Calendar.MONTH);
int month2 = dob.get(Calendar.MONTH);
if (month2 > month1) {
age--;
} else if (month1 == month2) {
int day1 = now.get(Calendar.DAY_OF_MONTH);
int day2 = dob.get(Calendar.DAY_OF_MONTH);
if (day2 > day1) {
age--;
}
}
} catch (ParseException e) {
e.printStackTrace();
}
return age ;
}
The fields birth and effect are both date fields:
Calendar bir = Calendar.getInstance();
bir.setTime(birth);
int birthNm = bir.get(Calendar.DAY_OF_YEAR);
int birthYear = bir.get(Calendar.YEAR);
Calendar eff = Calendar.getInstance();
eff.setTime(effect);
This basically a modification of John O's solution without using depreciated methods. I spent a fair amount of time trying to get his code to work in in my code. Maybe this will save others that time.
What about this one?
public Integer calculateAge(Date date) {
if (date == null) {
return null;
}
Calendar cal1 = Calendar.getInstance();
cal1.setTime(date);
Calendar cal2 = Calendar.getInstance();
int i = 0;
while (cal1.before(cal2)) {
cal1.add(Calendar.YEAR, 1);
i += 1;
}
return i;
}
String dateofbirth has the date of birth. and format is whatever (defined in the following line):
org.joda.time.format.DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern("mm/dd/yyyy");
Here is how to format:
org.joda.time.DateTime birthdateDate = formatter.parseDateTime(dateofbirth );
org.joda.time.DateMidnight birthdate = new org.joda.time.DateMidnight(birthdateDate.getYear(), birthdateDate.getMonthOfYear(), birthdateDate.getDayOfMonth() );
org.joda.time.DateTime now = new org.joda.time.DateTime();
org.joda.time.Years age = org.joda.time.Years.yearsBetween(birthdate, now);
java.lang.String ageStr = java.lang.String.valueOf (age.getYears());
Variable ageStr will have the years.
Elegant, seemingly correct, timestamp difference based variant of Yaron Ronen solution.
I am including a unit test to prove when and why it is not correct. It is impossible due (to possibly) different number of leap days (and seconds) in any timestamp difference. The discrepancy should be max +-1 day (and one second) for this algorithm, see test2(), whereas Yaron Ronen solution based on completely constant assumption of timeDiff / MILLI_SECONDS_YEAR can differ 10 days for a 40ty year old, nevertheless this variant is incorrect too.
It is tricky, because this improved variant, using formula diffAsCalendar.get(Calendar.YEAR) - 1970, returns correct results most of the time, as number of leap years in on average same between two dates.
/**
* Compute person's age based on timestamp difference between birth date and given date
* and prove it is INCORRECT approach.
*/
public class AgeUsingTimestamps {
public int getAge(Date today, Date dateOfBirth) {
long diffAsLong = today.getTime() - dateOfBirth.getTime();
Calendar diffAsCalendar = Calendar.getInstance();
diffAsCalendar.setTimeInMillis(diffAsLong);
return diffAsCalendar.get(Calendar.YEAR) - 1970; // base time where timestamp=0, precisely 1/1/1970 00:00:00
}
final static DateFormat df = new SimpleDateFormat("dd.MM.yyy HH:mm:ss");
#Test
public void test1() throws Exception {
Date dateOfBirth = df.parse("10.1.2000 00:00:00");
assertEquals(87, getAge(df.parse("08.1.2088 23:59:59"), dateOfBirth));
assertEquals(87, getAge(df.parse("09.1.2088 23:59:59"), dateOfBirth));
assertEquals(88, getAge(df.parse("10.1.2088 00:00:01"), dateOfBirth));
}
#Test
public void test2() throws Exception {
// between 2000 and 2021 was 6 leap days
// but between 1970 (base time) and 1991 there was only 5 leap days
// therefore age is switched one day earlier
// See http://www.onlineconversion.com/leapyear.htm
Date dateOfBirth = df.parse("10.1.2000 00:00:00");
assertEquals(20, getAge(df.parse("08.1.2021 23:59:59"), dateOfBirth));
assertEquals(20, getAge(df.parse("09.1.2021 23:59:59"), dateOfBirth)); // ERROR! returns incorrect age=21 here
assertEquals(21, getAge(df.parse("10.1.2021 00:00:01"), dateOfBirth));
}
}
public class CalculateAge {
private int age;
private void setAge(int age){
this.age=age;
}
public void calculateAge(Date date){
Calendar calendar=Calendar.getInstance();
Calendar calendarnow=Calendar.getInstance();
calendarnow.getTimeZone();
calendar.setTime(date);
int getmonth= calendar.get(calendar.MONTH);
int getyears= calendar.get(calendar.YEAR);
int currentmonth= calendarnow.get(calendarnow.MONTH);
int currentyear= calendarnow.get(calendarnow.YEAR);
int age = ((currentyear*12+currentmonth)-(getyears*12+getmonth))/12;
setAge(age);
}
public int getAge(){
return this.age;
}
/**
* Compute from string date in the format of yyyy-MM-dd HH:mm:ss the age of a person.
* #author Yaron Ronen
* #date 04/06/2012
*/
private int computeAge(String sDate)
{
// Initial variables.
Date dbDate = null;
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// Parse sDate.
try
{
dbDate = (Date)dateFormat.parse(sDate);
}
catch(ParseException e)
{
Log.e("MyApplication","Can not compute age from date:"+sDate,e);
return ILLEGAL_DATE; // Const = -2
}
// Compute age.
long timeDiff = System.currentTimeMillis() - dbDate.getTime();
int age = (int)(timeDiff / MILLI_SECONDS_YEAR); // MILLI_SECONDS_YEAR = 31558464000L;
return age;
}
Here is the java code to calculate age in year, month and days.
public static AgeModel calculateAge(long birthDate) {
int years = 0;
int months = 0;
int days = 0;
if (birthDate != 0) {
//create calendar object for birth day
Calendar birthDay = Calendar.getInstance();
birthDay.setTimeInMillis(birthDate);
//create calendar object for current day
Calendar now = Calendar.getInstance();
Calendar current = Calendar.getInstance();
//Get difference between years
years = now.get(Calendar.YEAR) - birthDay.get(Calendar.YEAR);
//get months
int currMonth = now.get(Calendar.MONTH) + 1;
int birthMonth = birthDay.get(Calendar.MONTH) + 1;
//Get difference between months
months = currMonth - birthMonth;
//if month difference is in negative then reduce years by one and calculate the number of months.
if (months < 0) {
years--;
months = 12 - birthMonth + currMonth;
} else if (months == 0 && now.get(Calendar.DATE) < birthDay.get(Calendar.DATE)) {
years--;
months = 11;
}
//Calculate the days
if (now.get(Calendar.DATE) > birthDay.get(Calendar.DATE))
days = now.get(Calendar.DATE) - birthDay.get(Calendar.DATE);
else if (now.get(Calendar.DATE) < birthDay.get(Calendar.DATE)) {
int today = now.get(Calendar.DAY_OF_MONTH);
now.add(Calendar.MONTH, -1);
days = now.getActualMaximum(Calendar.DAY_OF_MONTH) - birthDay.get(Calendar.DAY_OF_MONTH) + today;
} else {
days = 0;
if (months == 12) {
years++;
months = 0;
}
}
}
//Create new Age object
return new AgeModel(days, months, years);
}
Easiest way without any libraries:
long today = new Date().getTime();
long diff = today - birth;
long age = diff / DateUtils.YEAR_IN_MILLIS;
With Java 8, we can calculate a person age with one line of code:
public int calCAge(int year, int month,int days){
return LocalDate.now().minus(Period.of(year, month, days)).getYear();
}
Simple solution in kotlin.
fun getAgeOfUser(date: String?) : Int {
if(date.isNullOrEmpty()) return 0
val calendar = Calendar.getInstance()
val cYear = calendar.get(Calendar.YEAR)
val cDay = calendar.get(Calendar.DAY_OF_YEAR)
val dob = Calendar.getInstance()
dob.timeInMillis = date.toLong()
val bYear = dob.get(Calendar.YEAR)
val bDay = dob.get(Calendar.DAY_OF_YEAR)
var age = cYear - bYear
if(cDay < bDay) age--
return age
}
public int getAge(Date dateOfBirth)
{
Calendar now = Calendar.getInstance();
Calendar dob = Calendar.getInstance();
dob.setTime(dateOfBirth);
if (dob.after(now))
{
throw new IllegalArgumentException("Can't be born in the future");
}
int age = now.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
if (now.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR))
{
age--;
}
return age;
}
import java.io.*;
class AgeCalculator
{
public static void main(String args[])
{
InputStreamReader ins=new InputStreamReader(System.in);
BufferedReader hey=new BufferedReader(ins);
try
{
System.out.println("Please enter your name: ");
String name=hey.readLine();
System.out.println("Please enter your birth date: ");
String date=hey.readLine();
System.out.println("please enter your birth month:");
String month=hey.readLine();
System.out.println("please enter your birth year:");
String year=hey.readLine();
System.out.println("please enter current year:");
String cYear=hey.readLine();
int bDate = Integer.parseInt(date);
int bMonth = Integer.parseInt(month);
int bYear = Integer.parseInt(year);
int ccYear=Integer.parseInt(cYear);
int age;
age = ccYear-bYear;
int totalMonth=12;
int yourMonth=totalMonth-bMonth;
System.out.println(" Hi " + name + " your are " + age + " years " + yourMonth + " months old ");
}
catch(IOException err)
{
System.out.println("");
}
}
}
public int getAge(String birthdate, String today){
// birthdate = "1986-02-22"
// today = "2014-09-16"
// String class has a split method for splitting a string
// split(<delimiter>)
// birth[0] = 1986 as string
// birth[1] = 02 as string
// birth[2] = 22 as string
// now[0] = 2014 as string
// now[1] = 09 as string
// now[2] = 16 as string
// **birth** and **now** arrays are automatically contains 3 elements
// split method here returns 3 elements because of yyyy-MM-dd value
String birth[] = birthdate.split("-");
String now[] = today.split("-");
int age = 0;
// let us convert string values into integer values
// with the use of Integer.parseInt(<string>)
int ybirth = Integer.parseInt(birth[0]);
int mbirth = Integer.parseInt(birth[1]);
int dbirth = Integer.parseInt(birth[2]);
int ynow = Integer.parseInt(now[0]);
int mnow = Integer.parseInt(now[1]);
int dnow = Integer.parseInt(now[2]);
if(ybirth < ynow){ // has age if birth year is lesser than current year
age = ynow - ybirth; // let us get the interval of birth year and current year
if(mbirth == mnow){ // when birth month comes, it's ok to have age = ynow - ybirth if
if(dbirth > dnow) // birth day is coming. need to subtract 1 from age. not yet a bday
age--;
}else if(mbirth > mnow){ age--; } // birth month is comming. need to subtract 1 from age
}
return age;
}
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.Period;
public class AgeCalculator1 {
public static void main(String args[]) {
LocalDate start = LocalDate.of(1970, 2, 23);
LocalDate end = LocalDate.now(ZoneId.systemDefault());
Period p = Period.between(start, end);
//The output of the program is :
//45 years 6 months and 6 days.
System.out.print(p.getYears() + " year" + (p.getYears() > 1 ? "s " : " ") );
System.out.print(p.getMonths() + " month" + (p.getMonths() > 1 ? "s and " : " and ") );
System.out.print(p.getDays() + " day" + (p.getDays() > 1 ? "s.\n" : ".\n") );
}//method main ends here.
}
I appreciate all correct answers but this is the kotlin answer for the same question
I hope would be helpful to kotlin developers
fun calculateAge(birthDate: Date): Int {
val now = Date()
val timeBetween = now.getTime() - birthDate.getTime();
val yearsBetween = timeBetween / 3.15576e+10;
return Math.floor(yearsBetween).toInt()
}

Categories

Resources