elixir-cldr / cldr_calendars

Calendar functions for CLDR
Other
15 stars 6 forks source link

Cldr.Calendar.previous(range, :month) sometimes is in error #3

Closed kipcole9 closed 5 years ago

kipcole9 commented 5 years ago

In a week-based calendar, the idea of a "month" is notional and is represented by the :weeks_in_month configuration key. In some cases the Cldr.Calendar.previous/2 function is returning a result that is 2 "months" back, not one.

For example:

  defmodule C454 do
    use Cldr.Calendar.Base.Week,
      day_of_week: 7,
      first_or_last: :first,
      min_days_in_first_week: 7,
      month_of_year: 2,
      weeks_in_month: [4, 5, 4]
  end

  test "a descending sequence of months in a week calendar follow each other" do
    {:ok, d} = Date.new(2030, 1, 1, C454)
    m = Cldr.Calendar.Interval.month(d)
    Enum.reduce 1..1000, m, fn _i, m ->
      m2 = Cldr.Calendar.previous(m, :month)
      assert Cldr.Calendar.date_to_iso_days(m2.last) + 1 == Cldr.Calendar.date_to_iso_days(m.first)
      m2
    end
  end

Will error with:

code:  assert Cldr.Calendar.date_to_iso_days(m2.last()) + 1 == Cldr.Calendar.date_to_iso_days(m.first())
left:  741448
right: 741476

Decoded, this means:

Month: #DateRange<~D[2030-W01-1 Cldr.Calendar.PeriodSequenceTest.C454], ~D[2030-W04-7 Cldr.Calendar.PeriodSequenceTest.C454]>; 
Previous: #DateRange<~D[2029-W44-1 Cldr.Calendar.PeriodSequenceTest.C454], ~D[2029-W48-7 Cldr.Calendar.PeriodSequenceTest.C454]>

Which is 2 months back, not one.

bglusman commented 5 years ago

Thanks Kip! Note for anyone else looking at this, it can also manifest as "previous" month being equal to current month dates, suspect this is the same bug but I was unsure whether to open one issue or two so spoke to Kip and he thinks he has the source/is probably one bug for both.

kipcole9 commented 5 years ago

I have push a commit which I believe fixes this problem. I added a series of test to confirm that next and previous periods align properly to each other. If possible please test on master branch before I push to hex if you can.