Skip to content

Commit bc1bdcc

Browse files
committed
Fix shift_day/4 and add Julian variants
1 parent 10085cf commit bc1bdcc

File tree

7 files changed

+90
-13
lines changed

7 files changed

+90
-13
lines changed

lib/cldr/calendar/calendars/julian_compiler.ex

Lines changed: 67 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,17 @@ defmodule Cldr.Calendar.Julian.Compiler do
1717
@new_year_starting_day start_day
1818

1919
@quarters_in_year 4
20+
@months_in_quarter 3
2021
@months_in_year Cldr.Calendar.Julian.months_in_year(0)
2122
@last_month_of_year rem(start_month + (@months_in_year - 1), @months_in_year)
2223

23-
defguard year_rollover(month, day) when month <= @new_year_starting_month and day < @new_year_starting_day
24+
@doc """
25+
These dates belong to the prior Julian year
26+
27+
"""
28+
defguard year_rollover(month, day)
29+
when month < @new_year_starting_month
30+
or (month == @new_year_starting_month and day < @new_year_starting_day)
2431

2532
# Adjust the year to be a Jan 1st starting year and carry
2633
# on
@@ -33,26 +40,76 @@ defmodule Cldr.Calendar.Julian.Compiler do
3340
Cldr.Calendar.Julian.date_to_iso_days(year, month, day)
3441
end
3542

36-
def naive_datetime_to_iso_days(year, month, day, 0, 0, 0, {0, 0}) do
37-
{date_to_iso_days(year, month, day), {0, 6}}
38-
end
39-
4043
# Adjust the year to be this calendars starting year
4144
def date_from_iso_days(iso_days) do
4245
{year, month, day} = Cldr.Calendar.Julian.date_from_iso_days(iso_days)
46+
date_from_julian_date(year, month, day)
47+
end
4348

44-
if month <= @new_year_starting_month and day < @new_year_starting_day do
45-
{year - 1, month, day}
46-
else
47-
{year, month, day}
48-
end
49+
def date_from_julian_date(year, month, day) when year_rollover(month, day) do
50+
{year - 1, month, day}
51+
end
52+
53+
def date_from_julian_date(year, month, day) do
54+
{year, month, day}
55+
end
56+
57+
def naive_datetime_to_iso_days(year, month, day, 0, 0, 0, {0, 0}) do
58+
{date_to_iso_days(year, month, day), {0, 6}}
4959
end
5060

5161
def naive_datetime_from_iso_days({iso_days, _}) do
5262
{year, month, day} = date_from_iso_days(iso_days)
5363
{year, month, day, 0, 0, 0, {0, 6}}
5464
end
5565

66+
def shift_date(year, month, day, duration) do
67+
Cldr.Calendar.shift_date(year, month, day, __MODULE__, duration)
68+
end
69+
70+
def plus(year, month, day, date_part, increment, options \\ [])
71+
72+
def plus(year, month, day, :years, years, options) do
73+
new_year =
74+
year + years
75+
76+
new_day =
77+
if Keyword.get(options, :coerce, false) do
78+
max_new_day = days_in_month(new_year, month)
79+
min(day, max_new_day)
80+
else
81+
day
82+
end
83+
84+
{year + years, month, new_day}
85+
end
86+
87+
def plus(year, month, day, :quarters, quarters, options) do
88+
months = quarters * @months_in_quarter
89+
plus(year, month, day, :months, months, options)
90+
end
91+
92+
def plus(year, month, day, :months, months, options) do
93+
months_in_year = months_in_year(year)
94+
{year_increment, new_month} = Cldr.Math.div_amod(month + months, months_in_year)
95+
new_year = year + year_increment
96+
97+
new_day =
98+
if Keyword.get(options, :coerce, false) do
99+
max_new_day = days_in_month(new_year, new_month)
100+
min(day, max_new_day)
101+
else
102+
day
103+
end
104+
105+
{new_year, new_month, new_day}
106+
end
107+
108+
def plus(year, month, day, :days, days, _options) do
109+
iso_days = date_to_iso_days(year, month, day) + days
110+
date_from_iso_days(iso_days)
111+
end
112+
56113
def days_in_year(year) do
57114
first_day = date_to_iso_days(year, @new_year_starting_month, @new_year_starting_day)
58115
first_day_next_year = date_to_iso_days(year + 1, @new_year_starting_month, @new_year_starting_day)
@@ -184,7 +241,6 @@ defmodule Cldr.Calendar.Julian.Compiler do
184241

185242
defdelegate valid_date?(year, month, day), to: Cldr.Calendar.Julian
186243
defdelegate leap_year?(year), to: Cldr.Calendar.Julian
187-
defdelegate plus(year, month, day, part, years, options), to: Cldr.Calendar.Julian
188244
defdelegate week(year, week), to: Cldr.Calendar.Julian
189245
defdelegate weeks_in_year(year), to: Cldr.Calendar.Julian
190246
defdelegate months_in_year(year), to: Cldr.Calendar.Julian
@@ -204,7 +260,6 @@ defmodule Cldr.Calendar.Julian.Compiler do
204260
defdelegate time_to_day_fraction(hour, minute, second, millisecond), to: Cldr.Calendar.Julian
205261
defdelegate time_from_day_fraction(fraction), to: Cldr.Calendar.Julian
206262
defdelegate shift_time(hour, minute, second, millisecond, duration), to: Cldr.Calendar.Julian
207-
defdelegate shift_date(year, month, day, duration), to: Cldr.Calendar.Julian
208263
defdelegate shift_naive_datetime(year, month, day, hour, minute, second, millisecond, duration), to: Cldr.Calendar.Julian
209264
defdelegate iso_days_to_end_of_day(iso_days), to: Cldr.Calendar.Julian
210265
defdelegate iso_days_to_beginning_of_day(iso_days), to: Cldr.Calendar.Julian

test/round_trip_test.exs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ defmodule Cldr.Calendar.RoundTrip.Test do
8888
end
8989

9090
test "that Cldr.Calendar.Julian.March25 dates all round trip" do
91-
for year <- 0001..1800,
91+
for year <- 0001..2200,
9292
month <- 1..12,
9393
day <- 1..28 do
9494
{:ok, julian} = Date.new(year, month, day, Cldr.Calendar.Julian.March25)
@@ -98,6 +98,28 @@ defmodule Cldr.Calendar.RoundTrip.Test do
9898
end
9999
end
100100

101+
test "that Cldr.Calendar.Julian.Jan1 dates all round trip" do
102+
for year <- 0001..2200,
103+
month <- 1..12,
104+
day <- 1..Cldr.Calendar.Julian.days_in_month(year, month) do
105+
{:ok, julian} = Date.new(year, month, day, Cldr.Calendar.Julian.Jan1)
106+
{:ok, iso} = Date.convert(julian, Calendar.ISO)
107+
{:ok, converted} = Date.convert(iso, Cldr.Calendar.Julian.Jan1)
108+
assert Date.compare(julian, converted) == :eq
109+
end
110+
end
111+
112+
test "that Cldr.Calendar.Julian.Jan1 dates are the same as Cldr.Calendar.Julian dates" do
113+
for year <- 0001..2200,
114+
month <- 1..12,
115+
day <- 1..Cldr.Calendar.Julian.days_in_month(year, month) do
116+
{:ok, julian_jan1} = Date.new(year, month, day, Cldr.Calendar.Julian.Jan1)
117+
{:ok, julian} = Date.convert(julian_jan1, Cldr.Calendar.Julian)
118+
{:ok, converted} = Date.convert(julian, Cldr.Calendar.Julian.Jan1)
119+
assert Date.compare(julian_jan1, converted) == :eq
120+
end
121+
end
122+
101123
if function_exported?(Code, :fetch_docs, 1) do
102124
test "that no module docs are generated for a backend" do
103125
assert {:docs_v1, _, :elixir, _, :hidden, %{}, _} = Code.fetch_docs(NoDocs.Cldr.Calendar)

0 commit comments

Comments
 (0)