Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

calculating age as on a date.....

18 views
Skip to first unread message

nag

unread,
Oct 30, 2009, 2:42:34 PM10/30/09
to
Hi,

I have to calculate the present of as on 20091101(yyyymmdd) of a given
date of birth. I hav the following file. I have the following file.


name dob (this not the part of datafile)
xx 19540501
yy 19660101
zz 19920802

here dob is in yyyymmdd (if the fraction of months is greater than 6
months then age take the higher value)

I have done with the following code(raw method) and i got the age. But
is there any simple method to calculate the same.

#age as at 01.11.2009
by=substr($0,8,4)+0
bm=substr($0,12,2)+0
bd=substr($0,14,2)+0
if(bd>1 && bm >=11){days=31-bd;months=12+11-1-bm;years=2009-1-by}
if(bd>1 && bm <11){days=31-bd;months=11-1-bm;years=2009-by}
if(bd==1 && bm >11){days=0;months=12+11-bm;years=2009-1-by}
if(bd==1 && bm <=11){days=0;months=11-bm;years=2009-by}
if(months>6 ){age=years+1}
if(months==6 && days>0){age=years+1}
if(months<6){age=years}
if(months==6 && days==0){age=years}
#--------------------

Ed Morton

unread,
Oct 30, 2009, 2:52:10 PM10/30/09
to

This:

gawk '{print systime() - mktime(gensub(/(....)(..)(..)/,"\\1 \\2 \\3
00 00 00","",$2))}' file

will print the number of seconds from the date in the file to today. I
expect you can figure the rest out...

Ed.

pop

unread,
Oct 30, 2009, 9:24:56 PM10/30/09
to
Ed Morton said the following on 10/30/2009 1:52 PM:
I thought systime and mktime gave # seconds since 1970 1 1 or am I
wrong? How does it handle years before 1970? The mktime of my version of
gawk returns -1 (GNU Awk 3.1.6) for dates before 1970.

--
(^\pop/^)
I'm lost... I've gone to look for myself.
If I should return before I get back, keep me here.
--

Hermann Peifer

unread,
Oct 31, 2009, 8:11:37 AM10/31/09
to
pop wrote:
> Ed Morton said the following on 10/30/2009 1:52 PM:
>>
>> gawk '{print systime() - mktime(gensub(/(....)(..)(..)/,"\\1 \\2 \\3
>> 00 00 00","",$2))}' file
>>
>> will print the number of seconds from the date in the file to today. I
>> expect you can figure the rest out...
>>
>> Ed.

> I thought systime and mktime gave # seconds since 1970 1 1 or am I
> wrong? How does it handle years before 1970?

With negative values, see here:

$ TZ=Etc/UTC awk 'BEGIN{print mktime("1969 1 1 0 0 0")}'
-31536000


> The mktime of my version of
> gawk returns -1 (GNU Awk 3.1.6) for dates before 1970.


-1 indicates a format error in the value you passed to mktime()

Hermann

Message has been deleted
Message has been deleted

nag

unread,
Oct 31, 2009, 8:53:35 AM10/31/09
to

Thank you. Its working in my system (UBUNTU 8.1), i have to check it
on my server (RHEL 4 ES). There is a little bit confusion in mktime
(gensub(blah blah blah...). I could not follow it.

To convert the seconds into years I am dividing it with 60/60/24/365.
Again I am converting the fraction part into months to get the age
nearer birthday.

Thank you alot.

Is there any other way to solve it(like which i did earlier) to get
the age in integer(of course age nearer birthday), 'coz i want to
calculate the age as on a future date?

pop

unread,
Oct 31, 2009, 9:17:54 AM10/31/09
to
Hermann Peifer said the following on 10/31/2009 7:11 AM:

> pop wrote:
>
>> I thought systime and mktime gave # seconds since 1970 1 1 or am I
>> wrong? How does it handle years before 1970?
>
> With negative values, see here:
>
> $ TZ=Etc/UTC awk 'BEGIN{print mktime("1969 1 1 0 0 0")}'
> -31536000
>
>
>> The mktime of my version of gawk returns -1 (GNU Awk 3.1.6) for dates
>> before 1970.
>
>
> -1 indicates a format error in the value you passed to mktime()
>
> Hermann
No... not a format error - guess it is a combination of my version of
gawk and "good old" windows :-(

Hermann Peifer

unread,
Oct 31, 2009, 9:25:40 AM10/31/09
to
nag wrote:
> Is there any other way to solve it(like which i did earlier) to get
> the age in integer(of course age nearer birthday), 'coz i want to
> calculate the age as on a future date?


This is based on Ed's solution and might be what you want:

BEGIN { future_date = "2010 1 1 0 0 0" }

{
print int( ( mktime(future_date) \
- mktime(gensub(/(....)(..)(..)/, "\\1 \\2 \\3 0 0 0", "", $2) )) / \
( 365.25 * 24 * 60 * 60 ) + .5 )
}

Hermann

Hermann Peifer

unread,
Oct 31, 2009, 9:33:43 AM10/31/09
to
pop wrote:
> Hermann Peifer said the following on 10/31/2009 7:11 AM:
>> pop wrote:
>>
>>> I thought systime and mktime gave # seconds since 1970 1 1 or am I
>>> wrong? How does it handle years before 1970?
>>
>> With negative values, see here:
>>
>> $ TZ=Etc/UTC awk 'BEGIN{print mktime("1969 1 1 0 0 0")}'
>> -31536000
>>
>>
>>> The mktime of my version of gawk returns -1 (GNU Awk 3.1.6) for dates
>>> before 1970.
>>
>>
>> -1 indicates a format error in the value you passed to mktime()
>>
>> Hermann
> No... not a format error - guess it is a combination of my version of
> gawk and "good old" windows :-(
>

The quoting rules are different on Windows, which might lead to format errors.

Hermann

pop

unread,
Oct 31, 2009, 10:28:24 AM10/31/09
to
Hermann Peifer said the following on 10/31/2009 8:33 AM:
Nope - definately a windows problem; observe:
d:\temp>gawk "BEGIN{print mktime(\"1970 1 1 0 0 0\")}"
21600 <------due to CST 6 hour time diff from UTC

d:\temp>gawk "BEGIN{print mktime(\"1969 1 1 0 0 0\")}"
-1 <-----indicates an error instead of a neg value

nag

unread,
Oct 31, 2009, 9:42:09 PM10/31/09
to

Yeah! it is giving results, but there is a small problem. Here I am
trying to get the age "nearer to given birth day", i.e., for example
if the age as on 2009/11/01 is 54 years 5 months 5 days, then it is
54years. If it is 54 years 6 months or higher it should be 55. I tried
by adding 1 to integer part, but it is giving wrong results where
months part is less than 6months.

Ed Morton

unread,
Nov 1, 2009, 12:42:31 AM11/1/09
to

Your statement about "if it is 54 years 6 months or higher it should be
55" is wrong since it depends which months have passed. For example, the
first 6 months of a year are 31+28+31+30+31+30=181 (or 182 in a leap
year) days while the last 6 months of a year are 31+31+30+31+30+31=184
days so for someone born on Dec 31st 54 years 6 months and 1 day would
be closer to 54 than 55.

You also have a problem with the above approach that it's using the
average number of seconds in a year, but you really need to calculate
using the number of seconds in each specific year since for someone
who's 1 year, 6 months and 2 days (or maybe it's 3 days - I don't care
enough to really figure it out) old, whether that makes their age 1 or 2
given your requirements will depend on whether Feb had 28 or 29 days
that year.

Those aren't awk language questions though, they're algorithm questions.
Do you already have an algorithm figured out that you'd like to learn
how to implement in awk?

Ed.

Hermann Peifer

unread,
Nov 1, 2009, 6:44:29 AM11/1/09
to
nag wrote:
> On Oct 31, 6:25 pm, Hermann Peifer <pei...@gmx.eu> wrote:
>> nag wrote:
>>> Is there any other way to solve it(like which i did earlier) to get
>>> the age in integer(of course age nearer birthday), 'coz i want to
>>> calculate the age as on a future date?
>> This is based on Ed's solution and might be what you want:
>>
>> BEGIN { future_date = "2010 1 1 0 0 0" }
>>
>> {
>> print int( ( mktime(future_date) \
>> - mktime(gensub(/(....)(..)(..)/, "\\1 \\2 \\3 0 0 0", "", $2) )) / \
>> ( 365.25 * 24 * 60 * 60 ) + .5 )
>>
>> }
>>
>> Hermann
>
> If it is 54 years 6 months or higher it should be 55. I tried
> by adding 1 to integer part, but it is giving wrong results where
> months part is less than 6months.

Rounding is already included in the above algorithm, as it adds 0.5 to the calculated difference in years, then it truncates the result to integer.

As Ed mentions in his mail, the algorithm doesn't actually count months and days, but uses the number of seconds in an "average" year ( 365.25 * 24 * 60 * 60 ). This is a rough approximation and you probably do not want to calculate some critical values for your mission to Mars in this way.

If you want to have a more precise result you have to follow Ed's advice, plus observe time zones for "future_date" and "birthday", perhaps worry about leap seconds, various calendars and their reforms (How old would Julius Caesar be on 1 Jan 2010?), etc. But all this would be unrelated to gawk and should be discussed elsewhere.

Hermann

Janis Papanagnou

unread,
Nov 1, 2009, 6:49:48 AM11/1/09
to
Hermann Peifer wrote:
> nag wrote:
>> On Oct 31, 6:25 pm, Hermann Peifer <pei...@gmx.eu> wrote:
>>> nag wrote:
>>>> Is there any other way to solve it(like which i did earlier) to get
>>>> the age in integer(of course age nearer birthday), 'coz i want to
>>>> calculate the age as on a future date?
>>> This is based on Ed's solution and might be what you want:
>>>
>>> [...]

>>
>> If it is 54 years 6 months or higher it should be 55. I tried
>> by adding 1 to integer part, but it is giving wrong results where
>> months part is less than 6months.
>
> Rounding is already included in the above algorithm, as it adds 0.5 to
> the calculated difference in years, then it truncates the result to
> integer.
>
> As Ed mentions in his mail, the algorithm doesn't actually count months
> and days, but uses the number of seconds in an "average" year ( 365.25 *
> 24 * 60 * 60 ). This is a rough approximation and you probably do not
> want to calculate some critical values for your mission to Mars in this
> way.
>
> If you want to have a more precise result you have to follow Ed's
> advice, plus observe time zones for "future_date" and "birthday",
> perhaps worry about leap seconds, various calendars and their reforms
> (How old would Julius Caesar be on 1 Jan 2010?), etc.

And use some more accurate value for the days-per-year (365.2425) in case
the "future date" is yet far away, as probably the "mission to Mars" is. ;-)

Janis

Ed Morton

unread,
Nov 1, 2009, 9:03:35 AM11/1/09
to

And, topically in my neighborhood this morning, daylight savings time.
You'd hate to arrive on Mars an hour after sunset and miss it :-).

Ed.

Loki Harfagr

unread,
Nov 1, 2009, 1:27:49 PM11/1/09
to
Sun, 01 Nov 2009 12:49:48 +0100, Janis Papanagnou did cat :

If too far away then it also may have to forget about the gregorian cal.
anyway, just in case of a new reform maybe using the algo in the
BEGIN block may help, like
mean_div10K=(10000*((97*366 )+((400-97)*365)))/400

> as probably the "mission to
> Mars" is. ;-)

and while at it, I hope (besides hoping they won't use win13.9976949 at the time)
that they'll prepare some fine converters between miles and metres
and also mind to mention the units in every formula ;-)

>
> Janis
>
>> But all this would be unrelated to gawk and should be discussed
>> elsewhere.

well, grinding numbers or roxys is always elsewhere...
essentially ,-)

0 new messages