🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.jbuilder.java.language
4 messages
4 total messages Started by Petar Popara Thu, 01 Dec 2005 17:56
java.sql.Date (homework)
#334
Author: Petar Popara
Date: Thu, 01 Dec 2005 17:56
18 lines
1406 bytes
I have a date of birth as:

java.sql.Date dateOfBirth = ...; // get from DB

I have java.util.Date as current time:

java.util.Date now = new java.util.Date();

I need to calculate how many years is someone old. I have tried this:

long oldnessInMillis = now.getTime() - dateOfBirth.getTime();
long oldnessInYears = (oldnessInMillis / (1000 * 60 * 60 * 24 * 365));

but I got unexpected results (bigger 21.5 times). Is it because of time 
zones or I have miscalculated it?

Thank you in advance. :> 
Re: java.sql.Date (homework)
#335
Author: Kevin Dean [TeamB]
Date: Thu, 01 Dec 2005 17:51
71 lines
3722 bytes
Petar Popara wrote:

>I have a date of birth as:
>
>java.sql.Date dateOfBirth = ...; // get from DB
>
>I have java.util.Date as current time:
>
>java.util.Date now = new java.util.Date();
>
>I need to calculate how many years is someone old. I have tried this:
>
>long oldnessInMillis = now.getTime() - dateOfBirth.getTime();
>long oldnessInYears = (oldnessInMillis / (1000 * 60 * 60 * 24 * 365));
>
>but I got unexpected results (bigger 21.5 times). Is it because of time 
>zones or I have miscalculated it?

Ah yes, fun with integers.

The problem is that the compiler, when it does the arithmetic with the 
numbers you have there, does it using integers by default.  That's fine 
right up until it gets to the last multiplication:

1000
*60 = 60,000
*60 = 3,600,000
*24 = 86,400,000
*365 = 31,536,000,000

To you and me, that looks fine, but the compiler is working with Java 
integers, which are represented in four bytes and therefore have a limited 
range (-2^31 to +(2^31-1) or -2,147,483,648 to +2,147,483,647 to be 
exact).  When you overflow an integer like that, the compiler just wraps 
around to the beginning again.

The final number actually ends up wrapping around the integer limit 7 
times, with a remainder of 1,471,228,928 or 21.44 times less than the 
number itself, hence your problem.

A better way to do this would be to force one of the constants to be a 
long integer, which will in turn force the compiler to do the calculation 
using long integers.  Keep in mind that the compiler will do so only at 
the point where you coerce one of the constants to a long integer, so the 
arithmetic up to that point will still be done with regular integers.

The recommended modification would be:

long oldnessInYears = (oldnessInMillis / (1000L * 60 * 60 * 24 * 365));

See the link below for a good discussion of Java data types and their 
limits.

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/datatypes.html

Now, if you want the calculation to be really accurate, you need to take 
leap years into consideration (every four years, except every hundred, 
except every four hundred).  I'll leave that as an exercise.  ;-)

-- 
Kevin Dean [TeamB]
Dolphin Data Development Ltd.
http://www.datadevelopment.com/

NEW WHITEPAPERS
Team Development with JBuilder and Borland Enterprise Server
Securing Borland Enterprise Server
http://www.datadevelopment.com/papers/index.html

Please see Borland's newsgroup guidelines at
http://info.borland.com/newsgroups/guide.html
Re: java.sql.Date (homework)
#338
Author: Daniel Becroft
Date: Thu, 01 Dec 2005 18:58
50 lines
2538 bytes
Petar Popara wrote:

> 
> I have a date of birth as:
> 
> java.sql.Date dateOfBirth = ...; // get from DB
> 
> I have java.util.Date as current time:
> 
> java.util.Date now = new java.util.Date();
> 
> I need to calculate how many years is someone old. I have tried this:
> 
> long oldnessInMillis = now.getTime() - dateOfBirth.getTime();
> long oldnessInYears = (oldnessInMillis / (1000 * 60 * 60 * 24 * 365));
> 
> but I got unexpected results (bigger 21.5 times). Is it because of time zones or I have
> miscalculated it?
> 
> Thank you in advance. :>

Do you need to have fractions of years? If not, then I would just do something like the following:

/* **************************************************************************** */
[ Untested ]

int adjustment = 0;

if now.GetMonth() < dateOfBirth.getMonth() then
    adjustment = -1;
if now.GetMonth == dateOfBirth.GetMonth() && now.GetDate() < dateOfBirth.getDate()
    adjustment = -1;

/* 
** If adjustment == 0, then the person has had their birthday this year, otherwise, we need to
** adjust for this.
*/
int age_in_years = now.GetYear() - dateOfBirth.GetYear() + adjustment;
/* **************************************************************************** */

This, personally, gives cleaner code. But that's just me.

-- 
Daniel Becroft
; =================================
"Real computer scientists don't comment their code. The identifiers are so long they can't afford
the disk space."

"Blue sparks and white smoke, the two most expensive components of any electrical system, and once
used up will cost a fortune to replace."
Re: java.sql.Date (homework)
#337
Author: Petar Popara
Date: Thu, 01 Dec 2005 19:18
2 lines
1017 bytes
Thank you. :) 
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads