/ lubridate Public

# Wrong as.period computation with negative intervals#285

Closed
opened this issue Dec 13, 2014 · 2 comments
Closed

# Wrong as.period computation with negative intervals #285

opened this issue Dec 13, 2014 · 2 comments
Labels
bug an unexpected problem or unintended behavior

### vspinu commented Dec 13, 2014

 ``````end <- ymd('1992-02-28') start <- ymd_hms('2010-12-05 01:02:03') int <- new_interval(start, end) start + as.period(int) ## "1992-02-27 UTC" `````` The result is exactly one day smaller. I expect it's a wrong computing with days in `.int_to_period`. The text was updated successfully, but these errors were encountered:

### vspinu commented Sep 30, 2015

 This one turned to be tough. Some more examples: ```start <- ymd('1992-03-01') (per <- as.period(new_interval(start, end))) # "-2d 0H 0M 0S" start + per # "1992-02-28 UTC" start <- ymd('1992-04-01') (per <- as.period(new_interval(start, end))) # "-1m -4d 0H 0M 0S" start + per # "1992-02-26 UTC" start <- ymd('1992-05-01') (per <- as.period(new_interval(start, end))) # "-2m -3d 0H 0M 0S" start + per # "1992-02-27 UTC"``` The main issue is that the computation of `as.period` assumes that the period between `start` and `end` is the negative of the period between `end` and `start`. This causes problems with the arithmetics because the addition of days takes into account the previous months of the `end` date. While subtracting the period from `end`, the number of days in the next month of `start` are used for computation. That because of the addition logic of POSIXlt follow year -> month -> day sequence. In principle there are two ways out. Either make `period(start, end)` be different from `period(end, start)`, or change the semantic of addition with negative intervals such that days are added first and then the month operation is performed. I feel that the first option is cleaner, but will likely result in a lot of existing code. The second option might have less severe consequences, but will result in asymmetric arithmetics which is hard to reason about. More-over, lubridate relies on internal `POSIXlt` conversions which are incompatible with this "reversed" arithmetics. Thus second option is probably not really an option.

### vspinu commented Sep 30, 2015

 I have implemented asymmetric arithmetics of positive/negative periods as suggested above. With this fix the following behaves as expected: ```(per <- as.period(new_interval(start, end))) # "-1d 0H 0M 0S" start + per # "1992-02-29 UTC" start <- ymd('1992-04-01') (per <- as.period(new_interval(start, end))) # "-1m -1d 0H 0M 0S" start + per # "1992-02-29 UTC" start <- ymd('1992-05-01') (per <- as.period(new_interval(start, end))) # "-2m -1d 0H 0M 0S" start + per #"1992-02-29 UTC"``` For the new semantics of the negative periods see these tests.