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}
#--------------------
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/^)
I'm lost... I've gone to look for myself.
If I should return before I get back, keep me here.
--
> 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
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?
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
The quoting rules are different on Windows, which might lead to format errors.
Hermann
d:\temp>gawk "BEGIN{print mktime(\"1969 1 1 0 0 0\")}"
-1 <-----indicates an error instead of a neg value
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.
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.
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
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
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.
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 ,-)