How to find difference in years between two dates?
thebjorn
BjornSteinarFjeldPettersen at gmail.com
Wed Jul 26 16:26:43 EDT 2006
Roy Smith wrote:
> "thebjorn" <bp.datakortet.no at gmail.com> wrote:
>
> > def age(born):
> > now = date.today()
> > birthday = date(now.year, born.month, born.day)
> > return now.year - born.year - (birthday > now and 1 or 0)
>
> I don't get that last line. There's two things in particular that are
> puzzling me.
>
> 1) What does "birthday > now" mean? It sounds like you haven't been born
> yet.
I'm making a (perhaps tenous) semantic distinction between birthdate,
the date you were born on, and birthday, an annual event that may or
may not have happened yet this year :-)
> 2) I find the "and 1 or 0" part very confusing. I can't remember all the
> minor rules about operator precedence, but I'm sure this works out to some
> clever hack involving boolean short-circuit evaluation to get around the
> lack of a ternary operator in python.
You're correct :-) the line was originally:
return now.year - born.year - (1 if birthday > now else 0)
which gave a nice traceback on the production server that didn't have
2.5 on it :-( The and/or short-circuit is a fairly well established
(yet divisive) pydiom, and I was going to say something about people
really ought to learn a few simple precedence rules, but then I
realized the parenthesis aren't needed in the above <ehm..> The
parenthesis are needed in a version someone else mentioned:
return now.year - born.year - (birthday > now)
but I wouldn't write that, just like I wouldn't write 1 + True..
> If I need to pull out the reference manual to decipher what an expression means,
> it's too complicated.
Nah, that's a little too restrictive I think. I will agree that the
and/or is more cute than functional, at least in this case. Since it
could also throw, how about:
def yeardiff(a, b):
y = a.year - b.year
if (a.month, a.day) < (b.month, b.day): # tuple comparison
y -= 1
return y
def age(born): return yeardiff(date.today(), born)
> if birthday > now:
> return now.year - born.year - 1
> else:
> return now.year - born.year
I prefer to hoist the common expression out of the branches so they
don't have an opportunity to get out of sync, but I get your point.
-- bjorn
More information about the Python-list
mailing list