7

The following code attempts to measure the difference in months between the last day of a year and the first day of a month in the following year.

QuantityMagnitude@DateDifference[{2018, 12, 31}, {2019, #, 1}, "Month"] & /@ Range@12

which produces

{0.0322581, 1.03571, 2.03571, 3.03333, 4.03333, .03333,
6.03333, 7.03226, 8.03333, 9.03333, 10.0333, 11.0333}

However, the results are not what I would expect. Specifically, I would expect the denominator in calculating the fractional part to be the number of days in that particular month, i.e.

1/{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} // N

{0.0322581, 0.0357143, 0.0322581, 0.0333333, 0.0322581, 0.0333333, 0.0322581, 0.0322581, 0.0333333, 0.0322581, 0.0333333, 0.0322581}

What appears to be used instead is a sequence of days in each month of the year which is;

31, 28, 28, 30, 30, 30, 30, 31, 30, 30, 30, 30

which doesn't make much sense. Not only that, but it leads to nonsensical results such as the following;

In[359]:= DateDifference[{2018, 12, 31}, {2019, 3, 28}, "Month"]

Out[359]= Quantity[3, "Months"]

In[360]:= DateDifference[{2018, 12, 31}, {2019, 3, 29}, "Month"]

Out[360]= Quantity[3.03571, "Months"]

In[361]:= DateDifference[{2018, 12, 31}, {2019, 3, 30}, "Month"]

Out[361]= Quantity[3.07143, "Months"]

In[362]:= DateDifference[{2018, 12, 31}, {2019, 3, 31}, "Month"]

Out[362]= Quantity[3, "Months"]

Is this a bug or am I missing something? I can't see how this would be a feature.

Many thanks for your thoughts.

Rohit Namjoshi
  • 10,212
  • 6
  • 16
  • 67
RobertNathaniel
  • 790
  • 4
  • 12
  • This seems perfectly reasonable. UnitConvert[Quantity[1.0, "Months"], "Days"] is not an integer multiple of days so this is expected. – flinty Jul 16 '20 at 12:37
  • I disagree. Your example above takes a month in isolation. The result is 30.4167 which is the average length of a month in a year (multiply by 12 to get 365). However, DateDifference in taking the difference between two specific dates - there is a context provided. Also, if you reread my post, you'll see that the denominator that is being used for the number of days in a month is not constant but does not appear to fit a pattern that makes sense (at least to me). – RobertNathaniel Jul 16 '20 at 12:39
  • 2
    You're asking for the date difference in units of months which is units of 30.4167 days. It's documented behaviour, not a bug. The unit cannot change depending on which month it's in. Use mixed radix units {"Month", "Day"} instead. – flinty Jul 16 '20 at 12:44
  • It sounds like some application of DateRange is really what you need instead: DateRange[{2018, 12, 31}, {2019, 3, 1}, "Month"]. Also your expectation1/{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} // N is wrong, you probably meant 1/Accumulate[{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}] // N because you started with a fixed date {2018, 12, 31} – flinty Jul 16 '20 at 12:52
  • @flinty: Oh I see. OK thanks, I will use mixed radix units instead then. – RobertNathaniel Jul 16 '20 at 12:52

1 Answers1

7

I have noticed this problem too. First, the OP's version.

Denominator@Rationalize@
    DateDifference[{2018, 12, 31}, {2019, #, 1}, "Month"][[1]] & /@ Range@12

{31, 28, 28, 30, 30, 30, 30, 31, 30, 30, 30, 30}

This was my solution.

dateDifference[from_, to_, u:"Month"] :=
 DateDifference[from + {0, 0, 1}, to + {0, 0, 1}, u]

Denominator@Rationalize@ dateDifference[{2018, 12, 31}, {2019, #, 1}, "Month"][[1]] & /@ Range@12

{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}

Chris Degnen
  • 30,927
  • 2
  • 54
  • 108