Skip to content

Commit e682d3b

Browse files
committed
add floor_div helper
1 parent 0155a73 commit e682d3b

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

lib/elixir/lib/calendar/iso.ex

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,9 @@ defmodule Calendar.ISO do
919919
end
920920
end
921921

922+
defp floor_div_positive_divisor(int1, int2) when int1 >= 0, do: div(int1, int2)
923+
defp floor_div_positive_divisor(int1, int2), do: -div(-int1 - 1, int2) - 1
924+
922925
@doc """
923926
Returns how many days there are in the given year-month.
924927
@@ -1854,7 +1857,7 @@ defmodule Calendar.ISO do
18541857
months_in_year = 12
18551858
total_months = year * months_in_year + month + months - 1
18561859

1857-
new_year = Integer.floor_div(total_months, months_in_year)
1860+
new_year = floor_div_positive_divisor(total_months, months_in_year)
18581861

18591862
new_month =
18601863
case rem(total_months, months_in_year) + 1 do
@@ -1977,7 +1980,7 @@ defmodule Calendar.ISO do
19771980

19781981
if total in @unix_range_microseconds do
19791982
microseconds = Integer.mod(total, @microseconds_per_second)
1980-
seconds = @unix_epoch + Integer.floor_div(total, @microseconds_per_second)
1983+
seconds = @unix_epoch + floor_div_positive_divisor(total, @microseconds_per_second)
19811984
precision = precision_for_unit(unit)
19821985
{date, time} = iso_seconds_to_datetime(seconds)
19831986
{:ok, date, time, {microseconds, precision}}
@@ -2106,9 +2109,8 @@ defmodule Calendar.ISO do
21062109
end
21072110

21082111
defp days_to_year(days) when days < 0 do
2109-
# floor_div(days, n) = -div(-days - 1, n) - 1 for negative days
2110-
y_min = -div(-days - 1, @days_per_nonleap_year) - 1
2111-
y_max = -div(-days - 1, @days_per_leap_year) - 1
2112+
y_min = floor_div_positive_divisor(days, @days_per_nonleap_year)
2113+
y_max = floor_div_positive_divisor(days, @days_per_leap_year)
21122114

21132115
{year, day_start} =
21142116
days_to_year_interpolated(
@@ -2123,8 +2125,8 @@ defmodule Calendar.ISO do
21232125
end
21242126

21252127
defp days_to_year(days) do
2126-
y_max = div(days, @days_per_nonleap_year)
2127-
y_min = div(days, @days_per_leap_year)
2128+
y_min = floor_div_positive_divisor(days, @days_per_leap_year)
2129+
y_max = floor_div_positive_divisor(days, @days_per_nonleap_year)
21282130

21292131
{year, day_start} =
21302132
days_to_year_interpolated(
@@ -2147,13 +2149,7 @@ defmodule Calendar.ISO do
21472149
d_diff = d_max - d_min
21482150

21492151
numerator = diff * (days - d_min)
2150-
2151-
offset =
2152-
if numerator >= 0 do
2153-
div(numerator, d_diff)
2154-
else
2155-
-div(-numerator - 1, d_diff) - 1
2156-
end
2152+
offset = floor_div_positive_divisor(numerator, d_diff)
21572153

21582154
mid = min + max(0, min(offset, diff))
21592155
d_mid = days_in_previous_years(mid)

0 commit comments

Comments
 (0)