NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: bin/50574 (lib/libutil/t_parsedate:relative test fails at times)



The following reply was made to PR bin/50574; it has been noted by GNATS.

From: David Holland <dholland-bugs%netbsd.org@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: bin/50574 (lib/libutil/t_parsedate:relative test fails at times)
Date: Sun, 3 Jan 2016 00:09:57 +0000

 On Fri, Jan 01, 2016 at 08:00:01PM +0000, David Holland wrote:
  >  That's an annoying one; it's not even clear what the right answer is.
 
 Three more or less arbitrarily solicited opinions have unanimously
 agreed that the answer should be July 2; that is, parsedate.y is
 correct and the test code is wrong.
 
 mktime() is obliged (by longtime convention and maybe standards) to
 preserve day counts when normalizing, but it's up to parsedate.y (and
 the test code) to decide when and how many times to call mktime to
 normalize.
 
 I see three alternatives:
 
 A. Add days in first, normalize, then add months and normalize again.
 B. Add months, normalize, then add days and normalize again, or,
    equivalently, add months and days and normalize once.
 C. Add months, normalize but clamp to the last day to avoid rollover,
    then add days and normalize.
 
 These produce the following results in the following corner cases:
 
                                         A       B       C
  * +6 months 2 days from Dec 31:        Jul 2   Jul 3   Jul 2
  * -6 months 2 days from Jul 2:         Dec 30  Dec 31  Dec 31
  * +6m/2d then -6m/2d from Dec 31:      Dec 30  Jan 1   Dec 31
  * +6 months 2 days from Apr 30:        Nov 2   Nov 1   Nov 1
  * -6 months 2 days from Nov 2:         May 1   Apr 30  Apr 30 
  * +6m/2d then -6m/2d from Apr 30:      May 1   Apr 29  Apr 29
 
 In the case immediately at hand (the first one) method B produces
 what's been characterized as the wrong answer, so it's clearly not the
 right choice. Method C beats method A on the grounds that adding and
 then subtracting the same amount of time yields the same day, but that
 only works for Dec 31, not for Apr 30.
 
 To make the Apr 30 case work in this fashion, we need a rule by which
 six months from Apr 30 is Oct 31, that is, preserving the number of
 days to the end of the month rather than from the beginning, as Robert
 Elz hinted at. The problem with this is that then you need to switch
 from days-from-start to days-to-end sometime in the middle of the
 month and that just moves the behavioral oddities. (One month from
 January 16th is... February 15th? 14th?) This doesn't seem like a
 winner.
 
 Or maybe instead do the following:
   - When adding time, add months first, and normalize preventing
     rollover. Then add days and normalize.
   - When subtracting time, subtract days first and normalize. Then
     subtract months preventing rollover.
 That produces these answers:
 
  * +6 months 2 days from Dec 31:        Jul 2
  * -6 months 2 days from Jul 2:         Dec 30
  * +6m/2d then -6m/2d from Dec 31:      Dec 30
  * +6 months 2 days from Apr 30:        Nov 1
  * -6 months 2 days from Nov 2:         Apr 30
  * +6m/2d then -6m/2d from Apr 30:      Apr 30
 
 but that fixes Apr 30 at the cost of breaking Dec 31, which isn't
 actually any better. Feh.
 
 I'm sort of inlined to suggest the following, although it would
 require a good bit of hacking on parsedate.y:
 
  - Apply each relative time or date offset in the order given and
    normalize after each step.
 
 Then "+6 months 2 days" from Dec 31 would be July 3, or July 2 if we
 rule that adding months should never cause a month rollover, but "+2
 days 6 months" would be July 2.
 
 -- 
 David A. Holland
 dholland%netbsd.org@localhost
 


Home | Main Index | Thread Index | Old Index