5
$\begingroup$

Bug introduced in v12.1.1 or earlier and fixed in v13.0.0


I am on Mathematica 12.1.1, running the following code and getting different results. Is it bug in DatePlus?

Setup

date1 = DateObject[{2020, 1, 30}]
activitytimeperiodcoveredbyoneperiodicpayment = "Month"
rng = Range[5]

Execution of DatePlus[]:

DatePlus[DateString[date1, "ISODate"], {#, 
    activitytimeperiodcoveredbyoneperiodicpayment}] & /@ rng
DatePlus[date1, {#, 
    activitytimeperiodcoveredbyoneperiodicpayment}] & /@ rng

Result:

{"Sat 29 Feb 2020 00:00:00", "Mon 30 Mar 2020 00:00:00", "Thu 30 Apr \
2020 00:00:00", "Sat 30 May 2020 00:00:00", "Tue 30 Jun 2020 \
00:00:00"}

{DateObject[{2020, 3, 1}, "Day", "Gregorian", -4.], 
 DateObject[{2020, 3, 30}, "Day", "Gregorian", -4.], 
 DateObject[{2020, 4, 30}, "Day", "Gregorian", -4.], 
 DateObject[{2020, 5, 30}, "Day", "Gregorian", -4.], 
 DateObject[{2020, 6, 30}, "Day", "Gregorian", -4.]}
```
$\endgroup$
2
  • $\begingroup$ Mathematica behaves differently with DateObject than DateList or DateString input, in your case, with DateObject it increases month without controlling the day overflow (we don't have 2020-2-30) so it goes to the next month, but with other types, it snaps to the last possible day without overflowing. $\endgroup$
    – Ben Izd
    Oct 25 '21 at 5:10
  • $\begingroup$ Exactly. Allowing some types to overflow and others not is inconsistent result from DatePlus and/or a bug in DateObject. $\endgroup$ Oct 25 '21 at 13:25
0
$\begingroup$

I find that it is more convenient to use EndOfMonth in such cases. I would define a safe date, for instance the beginning of the month, do the monthly shifts and then ask for the end of month.

date2 = DatePlus[date1, {-1, "BeginningOfMonth"}]

DatePlus[DateString[date2, "ISODate"], 
  {{#, activitytimeperiodcoveredbyoneperiodicpayment}, {1, "EndOfMonth"}}] & /@ rng
DatePlus[date2, 
  {{#, activitytimeperiodcoveredbyoneperiodicpayment}, {1, "EndOfMonth"}}] & /@ rng

(* 
{"Sat 29 Feb 2020 00:00:00", "Tue 31 Mar 2020 00:00:00", "Thu 30 Apr \
2020 00:00:00", "Sun 31 May 2020 00:00:00", "Tue 30 Jun 2020 00:00:00"}

{DateObject[{2020, 2, 29}, "Day", "Gregorian", 1.], 
 DateObject[{2020, 3, 31}, "Day", "Gregorian", 1.], 
 DateObject[{2020, 4, 30}, "Day", "Gregorian", 1.], 
 DateObject[{2020, 5, 31}, "Day", "Gregorian", 1.], 
 DateObject[{2020, 6, 30}, "Day", "Gregorian", 1.]}
*)
$\endgroup$
3
  • $\begingroup$ EndOfMonth is useful but in this case the day of each month is the 30th. For some months, like April, 30th is EndOfMonth. For other, like January, 30th is not. And then there is February, where EndOfMonth could be 28th or 29th. $\endgroup$ Oct 25 '21 at 13:40
  • $\begingroup$ I think that the examples above return the correct end of month in all instances you mentioned - am I missing your point ? $\endgroup$ Oct 25 '21 at 14:00
  • $\begingroup$ 30 Jan 2020 plus one month is 29 Feb 2020. 30 Jan 2020 plus two months is 30 Mar 2020. 30 Jan 2020 plus three months is 30 Apr 2020. $\endgroup$ Oct 25 '21 at 14:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.