@@ -208,23 +208,13 @@ defmodule Calendar.ISO do
208
208
209
209
# Converts count of days since 0000-01-01 to {year, month, day} tuple.
210
210
@ doc false
211
- @ doc since: "1.5.0"
212
- def date_from_iso_days ( days ) when days in 0 .. 3_652_424 do
211
+ def date_from_iso_days ( days ) when days in - 3_652_059 .. 3_652_424 do
213
212
{ year , day_of_year } = days_to_year ( days )
214
213
extra_day = if leap_year? ( year ) , do: 1 , else: 0
215
214
{ month , day_in_month } = year_day_to_year_date ( extra_day , day_of_year )
216
215
{ year , month , day_in_month + 1 }
217
216
end
218
217
219
- def date_from_iso_days ( days ) when days in - 3_652_059 .. - 1 do
220
- { year , day_of_year } = days_to_year ( - days )
221
- previous_extra_day = if leap_year? ( year ) , do: 1 , else: 0
222
- extra_day = if leap_year? ( year + 1 ) , do: 1 , else: 0
223
- day_of_year = @ days_per_nonleap_year + extra_day - day_of_year
224
- { month , day_in_month } = year_day_to_year_date ( extra_day , day_of_year )
225
- { - year - 1 , month , day_in_month + previous_extra_day }
226
- end
227
-
228
218
defp div_mod ( int1 , int2 ) do
229
219
div = div ( int1 , int2 )
230
220
rem = int1 - div * int2
@@ -761,20 +751,44 @@ defmodule Calendar.ISO do
761
751
if leap_year? ( year ) , do: 1 , else: 0
762
752
end
763
753
754
+ defp days_to_year ( days ) when days < 0 do
755
+ year_estimate = - div ( - days , @ days_per_nonleap_year ) - 1
756
+
757
+ { year , days_before_year } =
758
+ days_to_year ( year_estimate , days , days_to_end_of_epoch ( year_estimate ) )
759
+
760
+ leap_year_pad = if leap_year? ( year ) , do: 1 , else: 0
761
+ { year , leap_year_pad + @ days_per_nonleap_year + days - days_before_year }
762
+ end
763
+
764
764
defp days_to_year ( days ) do
765
- year = Integer . floor_div ( days , @ days_per_nonleap_year )
766
- { year , days_before_year } = days_to_year ( year , days , days_in_previous_years ( year ) )
765
+ year_estimate = div ( days , @ days_per_nonleap_year )
766
+
767
+ { year , days_before_year } =
768
+ days_to_year ( year_estimate , days , days_in_previous_years ( year_estimate ) )
769
+
767
770
{ year , days - days_before_year }
768
771
end
769
772
770
- defp days_to_year ( year , days1 , days2 ) when days1 < days2 do
773
+ defp days_to_year ( year , days1 , days2 ) when year < 0 and days1 >= days2 do
774
+ days_to_year ( year + 1 , days1 , days_to_end_of_epoch ( year + 1 ) )
775
+ end
776
+
777
+ defp days_to_year ( year , days1 , days2 ) when year >= 0 and days1 < days2 do
771
778
days_to_year ( year - 1 , days1 , days_in_previous_years ( year - 1 ) )
772
779
end
773
780
774
781
defp days_to_year ( year , _days1 , days2 ) do
775
782
{ year , days2 }
776
783
end
777
784
785
+ defp days_to_end_of_epoch ( year ) when year < 0 do
786
+ previous_year = year + 1
787
+
788
+ div ( previous_year , 4 ) - div ( previous_year , 100 ) + div ( previous_year , 400 ) +
789
+ previous_year * @ days_per_nonleap_year
790
+ end
791
+
778
792
defp days_in_previous_years ( 0 ) , do: 0
779
793
780
794
defp days_in_previous_years ( year ) do
0 commit comments