Branch: Tag:

2008-02-05

2008-02-05 21:34:47 by Martin Stjernholm <mast@lysator.liu.se>

Fixed stepping of days by months or years to work in a more useful way.
Previously e.g. Calendar.ISO.Day(2000,1,31)+Calendar.ISO.Month() would
return March 2nd since there aren't 31 days in February and the Calendar
module would instead step 30 days forward from February 1st.

This is counterintuitive and not useful in most cases; practice shows that
it's clearly better to keep the month correct and accept an offset in the
day-of-month, i.e. to get February 29th instead in the example above.

The same situation also exists when standing on a leap day and stepping by
years to a non-leap year. This patch fixes that case too.

It does however not fix stepping weeks by years, which currently works in an
inconsistent way wrt to days. That will be fixed in versions >= 7.7 with
compat goo.

NOTE: This change is not strictly compatible, but given the alternatives of
introducing a theoretical incompatibility and solving a very real and
repeatedly encountered problem, the choice isn't difficult.

Rev: lib/modules/Calendar.pmod/YMD.pike:1.28
Rev: lib/modules/Calendar.pmod/testsuite.in:1.16

1:   START_MARKER - dnl $Id: testsuite.in,v 1.15 2008/01/23 15:23:54 mast Exp $ + dnl $Id: testsuite.in,v 1.16 2008/02/05 21:34:47 mast Exp $      dnl NOTE:   dnl *every* time the Calendar tests have failed, it's not the
139:   test_eq([[Calendar.ISO.Week (2008, 1)->year_no()]], 2008)   test_eq([[Calendar.ISO.Year (Calendar.ISO.Week (2008, 1))->year_no()]], 2008)    + test_eq([[Calendar.ISO.Day (2007, 5, 31)->add (1, Calendar.ISO.Month())]], Calendar.ISO.Day (2007, 6, 30)) + test_eq([[Calendar.ISO.Day (2007, 5, 31)->add (2, Calendar.ISO.Month())]], Calendar.ISO.Day (2007, 7, 31)) + test_eq([[Calendar.ISO.Day (2007, 5, 31)->add (1, Calendar.ISO.Month())->add (1, Calendar.ISO.Month())]], Calendar.ISO.Day (2007, 7, 30)) + test_eq([[Calendar.ISO.Day (2007, 5, 31)->add (-1, Calendar.ISO.Month())]], Calendar.ISO.Day (2007, 4, 30)) + test_eq([[Calendar.ISO.Day (2007, 5, 31)->add (-2, Calendar.ISO.Month())]], Calendar.ISO.Day (2007, 3, 31)) + test_eq([[Calendar.ISO.Day (2007, 5, 31)->add (-1, Calendar.ISO.Month())->add (1, Calendar.ISO.Month())]], Calendar.ISO.Day (2007, 5, 30)) +  + test_eq([[Calendar.ISO.Day (1900, 1, 31)->add (1, Calendar.ISO.Month())]], Calendar.ISO.Day (1900, 2, 28)) + test_eq([[Calendar.ISO.Day (2000, 1, 31)->add (1, Calendar.ISO.Month())]], Calendar.ISO.Day (2000, 2, 29)) + test_eq([[Calendar.ISO.Day (2004, 1, 31)->add (1, Calendar.ISO.Month())]], Calendar.ISO.Day (2004, 2, 29)) +  + test_eq([[Calendar.ISO.Day (2004, 2, 29)->add (1, Calendar.ISO.Year())]], Calendar.ISO.Day (2005, 2, 28)) + test_eq([[Calendar.ISO.Day (2004, 2, 29)->add (4, Calendar.ISO.Year())]], Calendar.ISO.Day (2008, 2, 29)) + test_eq([[Calendar.ISO.Day (2004, 2, 29)->add (2, Calendar.ISO.Year())->add (2, Calendar.ISO.Year())]], Calendar.ISO.Day (2008, 2, 28)) + test_eq([[Calendar.ISO.Day (2004, 2, 29)->add (-1, Calendar.ISO.Year())]], Calendar.ISO.Day (2003, 2, 28)) + test_eq([[Calendar.ISO.Day (2004, 2, 29)->add (-4, Calendar.ISO.Year())]], Calendar.ISO.Day (2000, 2, 29)) + test_eq([[Calendar.ISO.Day (2004, 2, 29)->add (-2, Calendar.ISO.Year())->add (2, Calendar.ISO.Year())]], Calendar.ISO.Day (2004, 2, 28)) +    END_MARKER