Re: How to find difference in years between two dates?

2006-07-29 Thread thebjorn
John Machin wrote:
 I don't understand. The examples that I showed went from the last day
 of a month to the last day of another month. [...]

Q1: is ((date-4days)+4days) == date?
Q2: is (((date-4days)+1month)+4days) == date+1month?

Ok, let's use Python'ish syntax (including numbering the days from 0
upwards, and backwards from -1, the last day of the month), you want
the last day of a month plus a month be the last day of the next
month. Simplistically, something like:

   month[-1] + 1 month == (month+1)[-1]   {last-to-last}

but that's obviously not the entire rule you want, unless 4-30 + 1
month == 5-31? So you would also like to have:

   month[i] + 1 month = (month+1)[i] {lock-step}

we'd like yesterday to be a day ago? So for suitable i:

   month[i] - 1 day == month[i-1]  {yesterday-1}
   month[0] - 1 day == (month-1)[-1]   {yesterday-2}

which leads to a natural definition for when tomorrow is:

   month[i] + 1 day == month[i+1]   {tomorrow-1}
   month[-1] + 1 day == (month+1)[0]{tomorrow-2}

So far so good. Now let's count backwards:

   month[-1] - 1 day == month[-2]  by: yesterday-1
   month[-2] - 1 day == month[-3]  by: yesterday-1
   month[-3] - 1 day == month[-4]  by: yesterday-1
   etc.

In other words, if you insist that the last day of the month is a well
defined concept and you want a day ago to be yesterday then month[-4],
the forth-to-last day of the month, is necessarily also well
defined. Having a well defined month[i], I'll apply your rules for
adding a month:

   month[-4] + 1 month == (month+1)[-4]   by: last-to-last

but you don't like this, because that means that e.g.:

   april[-4] + 1 month == may[-4]
   april[27] + 1 month == may[28]

which in addition to {lock-step}:

   april[27] + 1 month == may[27]

either gives an inconsistent, ill-formed, or FUZZY system (although
I would call it regular ;-)

My approach is simpler since it doesn't define addition, only
subtraction on valid dates, so if I switch to representing dates as
(month, day):

   (a, b) - (c, d) := a - c   iff b  d   {subtract}
 else a - c - 1

{subtract} is irregular but well defined for all valid dates (it will
always give you an answer, and it's always the same answer ;-) :

   (2,29) - (1,31) == 0
   (3,1) - (1,31) == 2

I can add day addition and still be ok:

   (m,d) + 1 day := (m,d+1){tomorrow-1}
   (m,-1) + 1 day := (m+1,0)   {tomorrow-2}
   (m,d) - 1 day := (m,d-1)   {yesterday-1}
   (m,0) - 1 day := (m-1,-1)  {yesterday-2}

Now my system is well-formed and consitent, even though it is
irregular, and it will answer yes to Q1 above. I can't see a way of
adding month addition to this and stay consistent without enumerating
special cases for every month, so Q2 can't even be asked in my system.

  You're entitled to your opinion.

 And you to yours :-)

Ok, I've explained why I hold mine... You care to do the same?

-- bjorn

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-28 Thread Bruno Desthuilliers
thebjorn wrote:
 Bruno Desthuilliers wrote:
 Which conversion ? How do you get the data ? as a datetime object ? as a
 (y,m,d) tuple ? as a y-m-d string ? Else ?
 
 All input routines, whether they're from a web-form, database, command
 line, or anywhere else, only produce objects from the datetime module
 for calendar data.

Seems quite sensible.

 That way the program logic doesn't have to guess
 which format it's getting... I suppose I could do something like:
 
def age(born):
 mx_born = mx.DateTime.Date(born.year, born.month, born.day)
 ...

Yes, I was thinking of something like this.

 -- bjorn
 


-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-28 Thread thebjorn
John Machin wrote:
 Jan 31 to Feb 27: 27d (ex) 28d (in)
 Jan 31 to Feb 28: 28d (ex) 1m 1d (in)
 Jan 31 to Mar 01: 1m 1d (ex) 1m 2d (in)
 So 1 day short of 1m 1d is not 1m 0 d???

Exactly. Just as a person born on 1999-3-1 isn't a year old on
2000-2-29. Perfectly regular, consistent and reasonable.

 I'd call this unreasonable, inconsistent, anomalous -- especially
 when on the same website you do 1993-01-31 plus 1 month, it
 gives you 1993-02-28 (as I'd expect).

You're entitled to your opinion.

-- bjorn

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-28 Thread John Machin

thebjorn wrote:
 John Machin wrote:
  Jan 31 to Feb 27: 27d (ex) 28d (in)
  Jan 31 to Feb 28: 28d (ex) 1m 1d (in)
  Jan 31 to Mar 01: 1m 1d (ex) 1m 2d (in)
  So 1 day short of 1m 1d is not 1m 0 d???

 Exactly. Just as a person born on 1999-3-1 isn't a year old on
 2000-2-29. Perfectly regular, consistent and reasonable.

Is a person born on 1993-08-01 a year old on 1994--07-31?

I don't understand. The examples that I showed went from the last day
of a month to the last day of another month. You justify a manifest
inconsistency in the results by reference to an example that goes from
the first day of a month to the last day of a month??


  I'd call this unreasonable, inconsistent, anomalous -- especially
  when on the same website you do 1993-01-31 plus 1 month, it
  gives you 1993-02-28 (as I'd expect).
 
 You're entitled to your opinion.

And you to yours :-)

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-27 Thread Bruno Desthuilliers
thebjorn wrote:
 Bruno Desthuilliers wrote:
 [...]
 
Possible solution:

import mx.DateTime as dt
def age(date):
return dt.Age(dt.today(), date).years
born = dt.Date(1967, 5, 1)
assert age(born) == 39
 
 
 dealbreaker:

age(datetime.date(1970,5,2))

(snip traceback)

What about:
 age(dt.Date(1970,5,2))

 I'm getting data from a database, and conversions
 are out of the
 question for something like this.

Which conversion ? How do you get the data ? as a datetime object ? as a
(y,m,d) tuple ? as a y-m-d string ? Else ?



-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-27 Thread thebjorn
John Machin wrote:
 thebjorn wrote:
  John Machin wrote:
   thebjorn wrote:
[...]
   Holy code bloat, Batman! Try this:
  
   return now.year - born.year - (birthday  now)
 
  yuck :-)

 But this:
 return now.year - born.year - (birthday  now and 1 or 0) is not yuck???

Correct.

  [...]
   It's the irregular-size months that cause the problems. If you can work
   out the months difference, then just floor_div by 12 to get the years
   difference.
 
  I don't agree that the irregular sized months cause a problem in this
  case. They do cause a problem if you're asking when is today + one
  month?, i.e. there isn't an unambiguous answer to that question in
  general (e.g. if today was January 31). We're asking a different kind
  of question though: has it been at least one month since January 31?,
  the answer would be no on Feb 29 and yes on Mar 1.

 If a bank were paying you interest on a monthly basis, and you
 deposited money on Jan 31 and pulled it out on the last day of
 February, that would count as one month. This is what I call the today
 - yesterday == 1 rule. For computing things like duration of employee
 service, you need the today - yesterday == 2 rule -- on the
 assumption that service counts from start of business yesterday to
 close of business today. So hire date of 1 Feb to fire date of (last
 day of Feb) would count as one month.

You give a good argument that the concept of a month is fuzzy, I still
don't believe that it makes the concept of a year fuzzy (or that the
fuzziness of month needs to be accounted for when computing years).

 Sorry, I don't understand. Why are you speechless? What would I want to
 use the calendar module for? Apart from the leap() function and the
 table of days in a month, the calendar module doesn't have any of the
 functionality that one would expect in a general-purpose date class.

Well, I thought replacing a 4 line function with 31 lines, 13 of which
duplicated functionality in the standard library was overkill... I came
up with this yesterday which seems sufficient?

def yeardiff(a, b):
  y = a.year - b.year
  if (a.month, a.day)  (b.month, b.day): # tuple comparison
  y -= 1
  return y 

-- bjorn

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-27 Thread John Machin

thebjorn wrote:
 John Machin wrote:
  thebjorn wrote:
   John Machin wrote:
thebjorn wrote:
 [...]
Holy code bloat, Batman! Try this:
   
return now.year - born.year - (birthday  now)
  
   yuck :-)
 
  But this:
  return now.year - born.year - (birthday  now and 1 or 0) is not yuck???

 Correct.

   [...]
It's the irregular-size months that cause the problems. If you can work
out the months difference, then just floor_div by 12 to get the years
difference.
  
   I don't agree that the irregular sized months cause a problem in this
   case. They do cause a problem if you're asking when is today + one
   month?, i.e. there isn't an unambiguous answer to that question in
   general (e.g. if today was January 31). We're asking a different kind
   of question though: has it been at least one month since January 31?,
   the answer would be no on Feb 29 and yes on Mar 1.
 
  If a bank were paying you interest on a monthly basis, and you
  deposited money on Jan 31 and pulled it out on the last day of
  February, that would count as one month. This is what I call the today
  - yesterday == 1 rule. For computing things like duration of employee
  service, you need the today - yesterday == 2 rule -- on the
  assumption that service counts from start of business yesterday to
  close of business today. So hire date of 1 Feb to fire date of (last
  day of Feb) would count as one month.

 You give a good argument that the concept of a month is fuzzy

Sorry,  I can't imagine where you got fuzzy from. Perhaps you mean
some other word. The concept is capable of being expressed precisely.

 I still
 don't believe that it makes the concept of a year fuzzy (or that the
 fuzziness of month needs to be accounted for when computing years).

The point is to ensure that (say) 24 months of employment and 2 years
of employment are determined in a consistent fashion.


  Sorry, I don't understand. Why are you speechless? What would I want to
  use the calendar module for? Apart from the leap() function and the
  table of days in a month, the calendar module doesn't have any of the
  functionality that one would expect in a general-purpose date class.

 Well, I thought replacing a 4 line function with 31 lines, 13 of which
 duplicated functionality in the standard library was overkill.

I think you missed the point that the lines I quoted were straight out
of a self-contained library that existed (in C as well as Python) way
before the datetime module was a gleam in Fred  the timbot's eyes.
Even if I had noticed a leap year function in the calendar module, I
would probably not have used it. The Python version of the module was
just a stopgap while I fiddled with getting a C extension going. The C
leap year function doesn't have any of that modulo stuff in it.

 I came
 up with this yesterday which seems sufficient?

 def yeardiff(a, b):
   y = a.year - b.year
   if (a.month, a.day)  (b.month, b.day): # tuple comparison
   y -= 1
   return y

At least it doesn't blow up when b is leapyear-02-29. It just gives the
wrong answer when a is nonleapyear-02-28. E.g. it gives 0 years
difference  from 1992-02-29 to 1993-02-28 instead of 1.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-27 Thread thebjorn
John Machin wrote:
 thebjorn wrote:
[...]
  You give a good argument that the concept of a month is fuzzy

 Sorry,  I can't imagine where you got fuzzy from. Perhaps you mean
 some other word. The concept is capable of being expressed precisely.

and the second to last date in January plus a month is..?

   Sorry, I don't understand. Why are you speechless? What would I want to
   use the calendar module for? Apart from the leap() function and the
   table of days in a month, the calendar module doesn't have any of the
   functionality that one would expect in a general-purpose date class.
 
  Well, I thought replacing a 4 line function with 31 lines, 13 of which
  duplicated functionality in the standard library was overkill.

 I think you missed the point that the lines I quoted were straight out
 of a self-contained library that existed (in C as well as Python) way
 before the datetime module was a gleam in Fred  the timbot's eyes.

I'm guessing you missed that I was looking for a method in the stdlib
to do this, and failing that an idiomatic solution...

 Even if I had noticed a leap year function in the calendar module, I
 would probably not have used it. The Python version of the module was
 just a stopgap while I fiddled with getting a C extension going. The C
 leap year function doesn't have any of that modulo stuff in it.

I'm sure it doesn't. You might want to look at the assembly your C
compiler produces for a modulo-power-of-2 operation...

  I came up with this yesterday which seems sufficient?
 
  def yeardiff(a, b):
y = a.year - b.year
if (a.month, a.day)  (b.month, b.day): # tuple comparison
y -= 1
return y

 At least it doesn't blow up when b is leapyear-02-29. It just gives the
 wrong answer when a is nonleapyear-02-28. E.g. it gives 0 years
 difference  from 1992-02-29 to 1993-02-28 instead of 1.

I believe you're mistaken (but feel free to correct me), my grandmother
is born on Feb 29 and a quick call to my dad verified that they
celebrated it the day after the 28th (unless Mar 1 was a Monday ;-).
http://timeanddate.com/date/duration.html also seem to agree with my
current understanding, just as a datapoint if nothing else.

-- bjorn

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-27 Thread thebjorn
Bruno Desthuilliers wrote:
 Which conversion ? How do you get the data ? as a datetime object ? as a
 (y,m,d) tuple ? as a y-m-d string ? Else ?

All input routines, whether they're from a web-form, database, command
line, or anywhere else, only produce objects from the datetime module
for calendar data. That way the program logic doesn't have to guess
which format it's getting... I suppose I could do something like:

   def age(born):
mx_born = mx.DateTime.Date(born.year, born.month, born.day)
...

-- bjorn

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-27 Thread John Machin

thebjorn wrote:
 John Machin wrote:
  thebjorn wrote:
 [...]
   You give a good argument that the concept of a month is fuzzy
 
  Sorry,  I can't imagine where you got fuzzy from. Perhaps you mean
  some other word. The concept is capable of being expressed precisely.

 and the second to last date in January plus a month is..?

The last day in February, according to me and also according to the
website that you mention later, e.g.

From date: Thursday, January 30, 1992
Added 1 month
Resulting date: Saturday, February 29, 1992


The precise rule is that if the original day is later than the last day
of the target month, clip it to that last day.



  Even if I had noticed a leap year function in the calendar module, I
  would probably not have used it. The Python version of the module was
  just a stopgap while I fiddled with getting a C extension going. The C
  leap year function doesn't have any of that modulo stuff in it.

 I'm sure it doesn't. You might want to look at the assembly your C
 compiler produces for a modulo-power-of-2 operation...

I don't need to. AFAIR just about every compiler I've used (BDS C on a
Z80 is a likely exception) has generated  mask (with extra mucking
about if the first operand is signed). Leap year calc involves % 100
and % 400. Factoring out the powers of two leaves 25. Now tell me how
I'm managing that without a modulo operation.


   I came up with this yesterday which seems sufficient?
  
   def yeardiff(a, b):
 y = a.year - b.year
 if (a.month, a.day)  (b.month, b.day): # tuple comparison
 y -= 1
 return y
 
  At least it doesn't blow up when b is leapyear-02-29. It just gives the
  wrong answer when a is nonleapyear-02-28. E.g. it gives 0 years
  difference  from 1992-02-29 to 1993-02-28 instead of 1.

 I believe you're mistaken (but feel free to correct me), my grandmother
 is born on Feb 29 and a quick call to my dad verified that they
 celebrated it the day after the 28th (unless Mar 1 was a Monday ;-).
 http://timeanddate.com/date/duration.html also seem to agree with my
 current understanding, just as a datapoint if nothing else.

hmm ... let's look at more than 1 data point from that website:

easy cases Jan 1993 to Feb 1993:
Jan 10 to Feb  9: 30d (excluding last day)  1m 0d (including last day)
Jan 10 to Feb 10: 1m 0d  (excluding last day)  1m 1d (including last
day)
Jan 10 to Feb 11: 1m 1d  (excluding last day)  1m 2d (including last
day)
looks reasonable, consistent, no anomalies; note how 1m 0d (excluding)
is predicted from the right and below.

Now try from Jan 31 1993:
Jan 31 to Feb 27: 27d (ex) 28d (in)
Jan 31 to Feb 28: 28d (ex) 1m 1d (in)
Jan 31 to Mar 01: 1m 1d (ex) 1m 2d (in)
So 1 day short of 1m 1d is not 1m 0 d??? I'd call this unreasonable,
inconsistent, anomalous -- especially when on the same website you do
1993-01-31 plus 1 month, it gives you 1993-02-28 (as I'd expect).

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread John Machin
thebjorn wrote:
 For the purpose of finding someone's age I was looking for a way to
 find how the difference in years between two dates, so I could do
 something like:

   age = (date.today() - born).year

 but that didn't work (the timedelta class doesn't have a year
 accessor).

 I looked in the docs and the cookbook, but I couldn't find anything, so
 I came up with:

   def age(born):
   now = date.today()
   birthday = date(now.year, born.month, born.day)

Bad luck if the punter was born on 29 Feb and the current year is not a
leap year.

   return now.year - born.year - (birthday  now and 1 or 0)

Holy code bloat, Batman! Try this:

return now.year - born.year - (birthday  now)


 i.e. calculate the raw years first and subtract one if he hasn't had
 his birthday yet this year... It works, but I'd rather use a standard
 and generic approach if it exists...?


It's the irregular-size months that cause the problems. If you can work
out the months difference, then just floor_div by 12 to get the years
difference.

Below is some code from the ancient times when everybody and his dog
each had their own date class :-)

HTH,
John

8--- methods from a date class

   def months_until(self, to_date):
  Return number of months between from_date (self) and to_date.
  
  from_date = self
  signum = 1
  if from_date  to_date:
 from_date, to_date = to_date, from_date
 signum = -1
  d1, m1, y1 = from_date.day, from_date.month, from_date.year
  d2, m2, y2 = to_date.day, to_date.month, to_date.year
  mdiff = (y2 - y1) * 12 + m2 - m1
  if d2  d1 and (d2  28 or d2 != last_day_of_month(y2, m2)):
 # the test d2  28 is not necessary; it is an optimisation
 # to avoid calling last_day_of_month unnecessarily
 mdiff = mdiff - 1
  return mdiff * signum

   def years_until(self, to_date):
  Return number of years between from_date (self) and to_date.
  
  md = self.months_until(to_date)
  if md = 0:
 return md // 12
  else:
 # ensure division truncates towards zero
 return -((-md) // 12)

8--- module-level functions and constants

# days in month
_dim = (None, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

def last_day_of_month(y, m):
   Return day (1..31) which is last day of month m in year y
   
   if m == 2:
  return 28 + _leap(y)
   else:
  if not (1 = m = 12):
 raise DateError, month not in 1..12
  return _dim[m]

def _leap(y):
   if y % 4: return 0
   if y % 100: return 1
   if y % 400: return 0
   return 1

8

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread Bruno Desthuilliers
thebjorn wrote:
 For the purpose of finding someone's age I was looking for a way to
 find how the difference in years between two dates, so I could do
 something like:
 
   age = (date.today() - born).year
 
 but that didn't work (the timedelta class doesn't have a year
 accessor).
 
 I looked in the docs and the cookbook, but I couldn't find anything, so
 I came up with:
 
   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.e. calculate the raw years first and subtract one if he hasn't had
 his birthday yet this year... It works, but I'd rather use a standard
 and generic approach if it exists...?

You may want to have a look at mxDatetime, which has a RelativeDateTime
type that seems to do what you want:
http://www.egenix.com/files/python/mxDateTime.html


-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread Roy Smith
thebjorn [EMAIL PROTECTED] 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.

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.  If I need to pull out the reference 
manual to decipher what an expression means, it's too complicated.  Try 
something like:

if birthday  now:
   return now.year - born.year - 1
else:
   return now.year - born.year

It takes up a little more space, but it's bog easy to understand without 
scratching your head or diving into the manual to refresh your memory of 
obscure language details.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread John Machin
Bruno Desthuilliers wrote:
 thebjorn wrote:
  For the purpose of finding someone's age I was looking for a way to
  find how the difference in years between two dates, so I could do
  something like:
 
age = (date.today() - born).year
 
  but that didn't work (the timedelta class doesn't have a year
  accessor).
 
  I looked in the docs and the cookbook, but I couldn't find anything, so
  I came up with:
 
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.e. calculate the raw years first and subtract one if he hasn't had
  his birthday yet this year... It works, but I'd rather use a standard
  and generic approach if it exists...?

 You may want to have a look at mxDatetime, which has a RelativeDateTime
 type that seems to do what you want:
 http://www.egenix.com/files/python/mxDateTime.html


Which pieces of the following seem to be working to you?

 import mx.DateTime
 f = mx.DateTime.RelativeDateTimeDiff
 d = mx.DateTime.Date
 f(d(2000, 2, 29), d(2001, 2, 28))
RelativeDateTime instance for '-(-11)-(-28) HH:MM:SS' at 0xaee170
 f(d(2000, 2, 29), d(2001, 3, 1))
RelativeDateTime instance for '(-0001)-MM-(-01) HH:MM:SS' at 0xb06530
 f(d(2001, 1, 31), d(2001, 2, 28))
RelativeDateTime instance for '-MM-(-28) HH:MM:SS' at 0xaee170
 g = lambda x, y: f(y, x)
 g(d(2000, 2, 29), d(2001, 2, 28))
RelativeDateTime instance for '-(+11)-(+30) HH:MM:SS' at 0xb06580
 g(d(2000, 2, 29), d(2001, 3, 1))
RelativeDateTime instance for '(+0001)-MM-DD HH:MM:SS' at 0xaee170
 g(d(2001, 1, 31), d(2001, 2, 28))
RelativeDateTime instance for '-MM-(+28) HH:MM:SS' at 0xb06580


and going the other way, adding one month to 31 January gives you some
date in March which is ludicrous.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread Bruno Desthuilliers
John Machin wrote:
 Bruno Desthuilliers wrote:
 
thebjorn wrote:

For the purpose of finding someone's age I was looking for a way to
find how the difference in years between two dates, so I could do
something like:

  age = (date.today() - born).year

but that didn't work (the timedelta class doesn't have a year
accessor).

I looked in the docs and the cookbook, but I couldn't find anything, so
I came up with:

  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.e. calculate the raw years first and subtract one if he hasn't had
his birthday yet this year... It works, but I'd rather use a standard
and generic approach if it exists...?

You may want to have a look at mxDatetime, which has a RelativeDateTime
type that seems to do what you want:
http://www.egenix.com/files/python/mxDateTime.html

 
 
 Which pieces of the following seem to be working to you?

John, it seems you failed to notice the use of may and seems in my
post. IIRC, both are supposed to strongly suggest a lack of certitude.


-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread John Machin

Bruno Desthuilliers wrote:
 John Machin wrote:
  Bruno Desthuilliers wrote:

 
  Which pieces of the following seem to be working to you?

 John, it seems you failed to notice the use of may and seems in my
 post. IIRC, both are supposed to strongly suggest a lack of certitude.



I didn't fail to notice that you were seeming. Re-read my question:
It's asking you which bits you were seeming.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread bearophileHUGS
Roy Smith:
 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.  If I need to pull out the reference
 manual to decipher what an expression means, it's too complicated.  Try
 something like:

From the manual, 5.10:
(Note that neither and nor or restrict the value and type they return to False 
and True, but rather return the last evaluated argument. This is sometimes 
useful, e.g., if s is a string that should be replaced by a default value if 
it is empty, the expression s or 'foo' yields the desired value. Because not 
has to invent a value anyway, it does not bother to return a value of the same 
type as its argument, so e.g., not 'foo' yields False, not ''.)

Then are such things something good to remove from Python 3.0 (making
or and and always return True or False), to simplify the language, and
make it more clear and reduce the possibility of bugs?

Bye,
bearophile

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread Bruno Desthuilliers
John Machin wrote:
 Bruno Desthuilliers wrote:
 
John Machin wrote:

Bruno Desthuilliers wrote:

Which pieces of the following seem to be working to you?

John, it seems you failed to notice the use of may and seems in my
post. IIRC, both are supposed to strongly suggest a lack of certitude.

 
 I didn't fail to notice that you were seeming. Re-read my question:
 It's asking you which bits you were seeming.

OP problem:
age = (date.today() - born).year

Possible solution:

import mx.DateTime as dt
def age(date):
return dt.Age(dt.today(), date).years
born = dt.Date(1967, 5, 1)
assert age(born) == 39



-- 
bruno desthuilliers
python -c print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in '[EMAIL PROTECTED]'.split('@')])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread thebjorn
Roy Smith wrote:
 thebjorn [EMAIL PROTECTED] 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

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread thebjorn
John Machin wrote:
 thebjorn wrote:
[...]
 
def age(born):
now = date.today()
birthday = date(now.year, born.month, born.day)

 Bad luck if the punter was born on 29 Feb and the current year is not a
 leap year.

Good catch! Thanks!

[..]
 Holy code bloat, Batman! Try this:

 return now.year - born.year - (birthday  now)

yuck :-)

[...]
 It's the irregular-size months that cause the problems. If you can work
 out the months difference, then just floor_div by 12 to get the years
 difference.

I don't agree that the irregular sized months cause a problem in this
case. They do cause a problem if you're asking when is today + one
month?, i.e. there isn't an unambiguous answer to that question in
general (e.g. if today was January 31). We're asking a different kind
of question though: has it been at least one month since January 31?,
the answer would be no on Feb 29 and yes on Mar 1.

 Below is some code from the ancient times when everybody and his dog
 each had their own date class :-)
[...]

Wow. I'm speechless. (any reason you didn't want to use the calendar
module?)

-- bjorn

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread thebjorn
Bruno Desthuilliers wrote:
[...]
 Possible solution:

 import mx.DateTime as dt
 def age(date):
 return dt.Age(dt.today(), date).years
 born = dt.Date(1967, 5, 1)
 assert age(born) == 39

dealbreaker:

 age(datetime.date(1970,5,2))
Traceback (most recent call last):
  File stdin, line 1, in ?
  File c:\python24\lib\site-packages\mx\DateTime\DateTime.py, line
842, in RelativeDateTimeDiff
diff = date1 - date2
TypeError: unsupported operand type(s) for -: 'DateTime' and
'datetime.date'

I'm getting data from a database, and conversions are out of the
question for something like this. Otherwise it's a fine library :-)

-- bjorn

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread Gerhard Fiedler
On 2006-07-26 17:50:43, thebjorn wrote:

 I don't agree that the irregular sized months cause a problem in this
 case. They do cause a problem if you're asking when is today + one
 month?, i.e. there isn't an unambiguous answer to that question in
 general (e.g. if today was January 31). We're asking a different kind
 of question though: has it been at least one month since January 31?,
 the answer would be no on Feb 29 and yes on Mar 1.

It's still ambiguous. That's why pretty much no library offers months as
units of date differences. They offer days (like DateTimeDelta in
mxDateTime does). 

For example, the mxDateTime guys say about their RelativeDateTime (which
allows months as differences): 

Note that dates like Date(1999,1,30) + RelativeDateTime(months=+1) are not
supported. The package currently interprets these constructions as
Date(1999,2,1) + 30, thus giving the 1999-03-02 which may not be what you'd
expect.


I think your original approach (difference of years, adjusted for whether
the date of the birthday has already passed in the current year or not) is
the unambiguous way to get the age. Other methods based on date differences
in days need careful adjustments for odd cases involving leap years.

Gerhard

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: How to find difference in years between two dates?

2006-07-26 Thread John Machin
thebjorn wrote:
 John Machin wrote:
  thebjorn wrote:
 [...]
  
 def age(born):
 now = date.today()
 birthday = date(now.year, born.month, born.day)
 
  Bad luck if the punter was born on 29 Feb and the current year is not a
  leap year.

 Good catch! Thanks!

Easy catch -- happens at least one per inning[s]  :-)


 [..]
  Holy code bloat, Batman! Try this:
 
  return now.year - born.year - (birthday  now)

 yuck :-)

But this:
return now.year - born.year - (birthday  now and 1 or 0)
is not yuck???


 [...]
  It's the irregular-size months that cause the problems. If you can work
  out the months difference, then just floor_div by 12 to get the years
  difference.

 I don't agree that the irregular sized months cause a problem in this
 case. They do cause a problem if you're asking when is today + one
 month?, i.e. there isn't an unambiguous answer to that question in
 general (e.g. if today was January 31). We're asking a different kind
 of question though: has it been at least one month since January 31?,
 the answer would be no on Feb 29 and yes on Mar 1.

If a bank were paying you interest on a monthly basis, and you
deposited money on Jan 31 and pulled it out on the last day of
February, that would count as one month. This is what I call the today
- yesterday == 1 rule. For computing things like duration of employee
service, you need the today - yesterday == 2 rule -- on the
assumption that service counts from start of business yesterday to
close of business today. So hire date of 1 Feb to fire date of (last
day of Feb) would count as one month.


  Below is some code from the ancient times when everybody and his dog
  each had their own date class :-)
 [...]

 Wow. I'm speechless. (any reason you didn't want to use the calendar
 module?)

Sorry, I don't understand. Why are you speechless? What would I want to
use the calendar module for? Apart from the leap() function and the
table of days in a month, the calendar module doesn't have any of the
functionality that one would expect in a general-purpose date class.

-- 
http://mail.python.org/mailman/listinfo/python-list