-5

Since it seems like people are more concerned about voting down than reading the actual question, the values I should be getting are in the bottom box, and my question is right under it

I need to find the age of a child based on a user entered birth date and today's date. The user has the option of viewing the age in years, months, weeks, and days. I need to make sure that the calculations account for leap years. I have gone through several posts that suggest different tricks, but so far I haven't found anything that calculates reliable numbers. The closest I've come to a solution is:

final Calendar bday = Calendar.getInstance();
bday.set(1991, 3, 27);

final Calendar today = Calendar.getInstance();

int yearsDiff = today.get(Calendar.YEAR) - bday.get(Calendar.YEAR); // yearsDiff: 24

if(bday.get(Calendar.MONTH) > today.get(Calendar.MONTH) ||
        (bday.get(Calendar.MONTH) == today.get(Calendar.MONTH) && bday.get(Calendar.DATE) > today.get(Calendar.DATE))) {
    yearsDiff --;
}

final int monthsDiff = yearsDiff * 12 + today.get(Calendar.MONTH) - bday.get(Calendar.MONTH); // monthsDiff: 296

final long timeOne = bday.getTime().getTime();
final long timeTwo = today.getTime().getTime();
final long oneDay = 1000 * 60 * 60 * 24;
final long delta = (timeTwo - timeOne) / oneDay;

final long year = delta / 365; // year: 24
final long rest = delta % 365; // rest: 232 delta: 8992
final long month = rest / 30;  // month: 7
final long rest2 = rest % 30;  // rest2: 22 rest: 232
final long weeks = rest2 / 7;  // weeks: 3
final long days = rest2 % 7;   // days: 1 rest2: 22

yearsDiff and monthsDiff are both correct. Correct values (as of today, 12-09-2015) are:

 years: 24
months: 296
 weeks: 1289
  days: 9023

You'll notice that there are two different I'm calculating some of these values. That's because I'm looking through different answers and trying to find the best solution.

How can I find the correct count of weeks and days?

Cody Harness
  • 1,116
  • 3
  • 18
  • 37
  • 3
    what is the question? – Dima Dec 09 '15 at 15:22
  • @Dima Look at the last box. The values are not lining up with what they should be. – Cody Harness Dec 09 '15 at 15:25
  • It's not clear in what way they're "not lining up" - which do you think is wrong, and what should it be? – Jon Skeet Dec 09 '15 at 15:35
  • @JonSkeet Again, look at the box on the bottom, which I said has the correct values in it. – Cody Harness Dec 09 '15 at 15:36
  • 1
    Ah, I'd misread and thought those were what you were seeing. Makes a bit more sense now, although it doesn't help that you haven't shown the actual results in the same format. Frankly I'd try to use Joda Time for all of this... are you able to do that? – Jon Skeet Dec 09 '15 at 15:37
  • @JonSkeet Comments in the code have the actual calculated values. At this point using a plugin would not be possible. – Cody Harness Dec 09 '15 at 15:40
  • 1
    Not all years have 365 days. Not all months are 30 days long. Your code is all wrong. Besides, in the code you are trying to compute the answer in the form of (N years PLUS M months PLUS ...), and your "box" with correct answers has (total years, total months, etc.) this would not match even if the code was correct. – Dima Dec 09 '15 at 15:41
  • Exactly - where's the equivalent to the "296 months" or "9023 days"? You've made it relatively hard for us to help you... – Jon Skeet Dec 09 '15 at 15:43
  • joda time is not a "plugin", it is a part of the JDK. Check this out: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html – Dima Dec 09 '15 at 15:45
  • Are you all not even reading my question? I already said that it needs to account for leap years. I'm fully aware that not all months have the same number of days. As for the box not having the right values, those are the correctly calculated values for those two dates. Those are the values that I need to get the code to give me. – Cody Harness Dec 09 '15 at 15:47
  • @Dima, No, joda time is a time manipulation library, it is not a part of JDK8. JDK8's new time api has been developed with the same person included, but it is not the same. – Aleksandar Stojadinovic Dec 09 '15 at 15:47
  • @CodyHarness I am reading your question, just having hard time understanging what it is you are asking. Would you like me to just write the correct code for you? I would be open to that. My rate is $250 per hour, and this is not an easy problem to solve, so you can expect the bill to be in the thousands ... – Dima Dec 09 '15 at 15:49
  • You can find the correct count of week and date by dropping all your assumptions about the length of years and months and preferably use a established Library (JDK8 datetime API or Joda Time) to do your calculations. In your case you're asking the wrong question. It should be "how can I correctly calculate the times I want to calculate" as your basic assumptions are wrong. – Aron_dc Dec 09 '15 at 15:54
  • @ViktorYakunin zaviduesh ... – Dima Dec 09 '15 at 15:54
  • @Dima Stackoverflow is where people come to ask questions when their code isn't working and a community of people can help them with their problem. Your comment is not helpful at all, and an arrogant way of telling me you have no interest in doing exactly what stackoverflow is about. – Cody Harness Dec 09 '15 at 15:54
  • 1
    @CodyHarness you are not asking questions. You are asking people to do your homework for you. This is not at all what SO is about, not even close. – Dima Dec 09 '15 at 15:55
  • Also your question is possibly already answered by: http://stackoverflow.com/questions/1555262/calculating-the-difference-between-two-java-date-instances – Aron_dc Dec 09 '15 at 15:56
  • 1
    @Aron_dc, one would have to drop the assumption about the length of a day too (not all days are 24 hours long). – Dima Dec 09 '15 at 15:57
  • @Dima There is a question in the post, and I've already done work. I made a post because I'm having problems with the code I've written. – Cody Harness Dec 09 '15 at 15:59
  • @Aron_dc That's a C# question. – Cody Harness Dec 09 '15 at 16:00
  • 1
    @CodyHarness you are having problems with the code you have written , because you have written it incorrectly. You know what is wrong with it, but instead of attempting to fix the problems you know about, you are expecting people to do it for you. – Dima Dec 09 '15 at 16:01
  • @CodyHarness Nope it was a question linking to almost the very same question for different languages. I updated it personally for you to only link to the Java specific question. – Aron_dc Dec 09 '15 at 16:01
  • @Dima Clearly I don't know what is wrong, as I'm here asking for help. – Cody Harness Dec 09 '15 at 16:07
  • Well, I (and others) told you what is wrong: not all minutes are 60 seconds long, not all days are 24 hours long, not all months are 30 days long, not all years are 365 days long. So, now you know what's wrong. Back to the drawing board! – Dima Dec 09 '15 at 16:10
  • Please inform yourself about calendars (the physical ones) and dates. Additionally you can read http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time – Aron_dc Dec 09 '15 at 16:14

3 Answers3

2

You will always have problems if you try to roll your own date/time arithmetic. Use the functions provided by the JDK, java.util.Calendar and the new java.time package, or a library like Joda Time. Try:

Period.between(date-of-birth , today's date).
FrankGT
  • 117
  • 7
  • Forgot to mark this as the answer when it was posted. Ended up using [Joda Time](https://github.com/JodaOrg/joda-time). – Cody Harness Jul 08 '16 at 20:16
1

The problems you get with your solution are already explained by Aleksandar.

With Java 8 you can solve it like in this snippet.

note: As mentioned by Viktor this will not work with Android. So go for the solution with JodaTime.

LocalDateTime birthDate = LocalDateTime.of(1991, 3, 27, 0, 0);
LocalDateTime today = LocalDateTime.now();

long years = birthDate.until(today, ChronoUnit.YEARS);
long months = birthDate.until(today, ChronoUnit.MONTHS);
long weeks = birthDate.until(today, ChronoUnit.WEEKS);
long days = birthDate.until(today, ChronoUnit.DAYS);

System.out.println("years  = " + years);
System.out.println("months = " + months);
System.out.println("weeks  = " + weeks);
System.out.println("days   = " + days);

output

years  = 24
months = 296
weeks  = 1289
days   = 9023
SubOptimal
  • 22,518
  • 3
  • 53
  • 69
0

It's hard to explain easily what are you doing wrong. Commons sense says it should work, but I think this video explains it best in the world.

To keep it short, you have problems with leap seconds,some years have 366 days, it depends on the time zone of the first and second date, and some years obviously do not even exist as a whole :-) .

I don't know are you bound to use the API you are using, which is the pre-Java 8 API. Although people are allergic to this answer, but you should really use a library for this, like Joda Time. Even better, if you could possibly migrate to using Java 8, and the new API and leave one dependency out.

Java 8 example:

    LocalDate today = LocalDate.parse("2015-04-27");
    LocalDate bday = LocalDate.of(2013, 5, 15);
    long weeks = bday.until(today, ChronoUnit.WEEKS);
    long years = bday.until(today, ChronoUnit.YEARS);
    Period until = bday.until(today); //complex object, has multiple getters
Aleksandar Stojadinovic
  • 4,851
  • 1
  • 34
  • 56
  • Actually he/she has problems with leap years, months that are longer than 30 days, days that are longer/shorter than 24h and so on. There are many assumptions made in the OPs code that are just plain wrong and therefore just cant work reliably (there may be a case where this program outputs a correct value for a certain input). – Aron_dc Dec 09 '15 at 16:06