Skip to content

Commit fd7ff3b

Browse files
committed
Refactor Juilan compiler
1 parent 0b4273f commit fd7ff3b

File tree

2 files changed

+241
-126
lines changed

2 files changed

+241
-126
lines changed

lib/cldr/calendar/calendars/julian.ex

Lines changed: 20 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -11,132 +11,10 @@ defmodule Cldr.Calendar.Julian do
1111
@months_in_quarter 3
1212
@days_in_week 7
1313

14-
defmacro __using__(opts \\ []) do
15-
quote bind_quoted: [opts: opts] do
16-
{start_month, start_day} = Keyword.get(opts, :new_year_starting_month_and_day, {1, 1})
17-
18-
@new_year_starting_month start_month
19-
@new_year_starting_day start_day
20-
21-
@quarters_in_year 4
22-
@months_in_year Cldr.Calendar.Julian.months_in_year(0)
23-
@last_month_of_year rem(start_month + (@months_in_year - 1), @months_in_year)
24-
25-
# Adjust the year to be a Jan 1st starting year and carry
26-
# on
27-
def date_to_iso_days(year, month, day) when month <= @new_year_starting_month and day < @new_year_starting_day do
28-
Cldr.Calendar.Julian.date_to_iso_days(year + 1, month, day)
29-
end
30-
31-
def date_to_iso_days(year, month, day) do
32-
Cldr.Calendar.Julian.date_to_iso_days(year, month, day)
33-
end
34-
35-
def naive_datetime_to_iso_days(year, month, day, 0, 0, 0, {0, 0}) do
36-
{date_to_iso_days(year, month, day), {0, 0}}
37-
end
38-
39-
# Adjust the year to be this calendars starting year
40-
def date_from_iso_days(iso_days) do
41-
{year, month, day} = Cldr.Calendar.Julian.date_from_iso_days(iso_days)
42-
43-
if month <= @new_year_starting_month and day < @new_year_starting_day do
44-
{year + 1, month, day}
45-
else
46-
{year, month, day}
47-
end
48-
end
49-
50-
# Here we use month to mean ordinal month. Therefore if the calendar
51-
# starts on March 25th, then days in month for March will be seen as
52-
# days if month for month 1.
53-
54-
def days_in_month(year, ordinal_month) do
55-
adjusted_month =
56-
Cldr.Math.amod(ordinal_month + @new_year_starting_month - 1, @months_in_year)
57-
58-
adjusted_year =
59-
if adjusted_month < @new_year_starting_month, do: year + 1, else: year
60-
61-
cond do
62-
# The first month of the year will be short since the year starts
63-
# part way through the month
64-
adjusted_month == @new_year_starting_month ->
65-
days_in_julian_month = Cldr.Calendar.Julian.days_in_month(year, ordinal_month)
66-
days_in_julian_month - @new_year_starting_day
67-
68-
# The last month of the year will be "long" since the first part of the
69-
# first month that is before the start of year will be included
70-
adjusted_month == @last_month_of_year ->
71-
start_of_month =
72-
date_to_iso_days(adjusted_year, adjusted_month, 1)
73-
start_of_next_month =
74-
date_to_iso_days(adjusted_year, @new_year_starting_month, @new_year_starting_day)
75-
start_of_next_month - start_of_month
76-
77-
true ->
78-
Cldr.Calendar.Julian.days_in_month(year, adjusted_month)
79-
end
80-
end
81-
82-
def month(year, ordinal_month) do
83-
adjusted_month =
84-
Cldr.Math.amod(ordinal_month + @new_year_starting_month - 1, @months_in_year)
85-
86-
adjusted_year =
87-
if adjusted_month < @new_year_starting_month, do: year + 1, else: year
88-
89-
first_day =
90-
if adjusted_month == @new_year_starting_month, do: @new_year_starting_day, else: 1
91-
92-
{:ok, first} = Date.new(adjusted_year, adjusted_month, first_day, __MODULE__)
93-
first_iso_days = date_to_iso_days(year, adjusted_month, first_day)
94-
days_in_month = days_in_month(year, ordinal_month)
95-
96-
last_iso_days = first_iso_days + days_in_month - 1
97-
{year, month, day} = date_from_iso_days(last_iso_days)
98-
{:ok, last} = Date.new(year, month, day, __MODULE__)
99-
100-
Date.range(first, last, 1)
101-
end
102-
103-
def quarter_of_year(year, month, day) do
104-
month_of_year = month_of_year(year, month, day)
105-
106-
ceil(month_of_year / (@months_in_year / @quarters_in_year))
107-
end
108-
109-
# Returns the ordinal month accounting for a long month 12
110-
def month_of_year(_year, month, day)
111-
when month == @new_year_starting_month and day < @new_year_starting_day do
112-
@months_in_year
113-
end
114-
115-
def month_of_year(_year, month, _day) do
116-
Cldr.Math.amod(month - @new_year_starting_month + 1, @months_in_year)
117-
end
118-
119-
def day_of_year(year, month, day) do
120-
adjusted_year =
121-
if month < @new_year_starting_month, do: year + 1, else: year
122-
123-
first_day = date_to_iso_days(year, @new_year_starting_month, @new_year_starting_day)
124-
this_day = date_to_iso_days(adjusted_year, month, day)
125-
this_day - first_day + 1
126-
end
127-
128-
defdelegate valid_date?(year, month, day), to: Cldr.Calendar.Julian
129-
defdelegate leap_year?(year), to: Cldr.Calendar.Julian
130-
defdelegate plus(year, month, day, part, years, options), to: Cldr.Calendar.Julian
131-
defdelegate week(year, week), to: Cldr.Calendar.Julian
132-
defdelegate weeks_in_year(year), to: Cldr.Calendar.Julian
133-
defdelegate day_of_week(year, month, day, starts_on), to: Cldr.Calendar.Julian
134-
defdelegate day_of_era(year, month, day), to: Cldr.Calendar.Julian
135-
defdelegate iso_week_of_year(year, month, day), to: Cldr.Calendar.Julian
136-
defdelegate week_of_year(year, month, day), to: Cldr.Calendar.Julian
137-
defdelegate year_of_era(year), to: Cldr.Calendar.Julian
138-
defdelegate parse_date(date), to: Cldr.Calendar.Julian
139-
defdelegate date_to_string(year, month, day), to: Cldr.Calendar.Julian
14+
defmacro __using__(options \\ []) do
15+
quote bind_quoted: [options: options] do
16+
@options options
17+
@before_compile Cldr.Calendar.Julian.Compiler
14018
end
14119
end
14220

@@ -806,6 +684,22 @@ defmodule Cldr.Calendar.Julian do
806684
),
807685
to: Calendar.ISO
808686

687+
defdelegate datetime_to_string(
688+
year,
689+
month,
690+
day,
691+
hour,
692+
minute,
693+
second,
694+
microsecond,
695+
time_zone,
696+
zone_abbr,
697+
utc_offset,
698+
std_offset,
699+
format
700+
),
701+
to: Calendar.ISO
702+
809703
@doc false
810704
@impl Calendar
811705
defdelegate naive_datetime_to_string(
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
defmodule Cldr.Calendar.Julian.Compiler do
2+
3+
defmacro __before_compile__(env) do
4+
opts =
5+
Module.get_attribute(env.module, :options)
6+
|> Keyword.put(:calendar, env.module)
7+
|> Macro.escape()
8+
9+
quote bind_quoted: [opts: opts] do
10+
@behaviour Calendar
11+
@behaviour Cldr.Calendar
12+
13+
{start_month, start_day} = Keyword.get(opts, :new_year_starting_month_and_day, {1, 1})
14+
15+
@new_year_starting_month start_month
16+
@new_year_starting_day start_day
17+
18+
@quarters_in_year 4
19+
@months_in_year Cldr.Calendar.Julian.months_in_year(0)
20+
@last_month_of_year rem(start_month + (@months_in_year - 1), @months_in_year)
21+
22+
defguard year_rollover(month, day) when month <= @new_year_starting_month and day < @new_year_starting_day
23+
24+
# Adjust the year to be a Jan 1st starting year and carry
25+
# on
26+
def date_to_iso_days(year, month, day) when year_rollover(month, day) do
27+
Cldr.Calendar.Julian.date_to_iso_days(year + 1, month, day)
28+
end
29+
30+
def date_to_iso_days(year, month, day) do
31+
Cldr.Calendar.Julian.date_to_iso_days(year, month, day)
32+
end
33+
34+
def naive_datetime_to_iso_days(year, month, day, 0, 0, 0, {0, 0}) do
35+
{date_to_iso_days(year, month, day), {0, 0}}
36+
end
37+
38+
# Adjust the year to be this calendars starting year
39+
def date_from_iso_days(iso_days) do
40+
{year, month, day} = Cldr.Calendar.Julian.date_from_iso_days(iso_days)
41+
42+
if month <= @new_year_starting_month and day < @new_year_starting_day do
43+
{year + 1, month, day}
44+
else
45+
{year, month, day}
46+
end
47+
end
48+
49+
def days_in_year(year) do
50+
first_day = date_to_iso_days(year, @new_year_starting_month, @new_year_starting_day)
51+
first_day_next_year = date_to_iso_days(year + 1, @new_year_starting_month, @new_year_starting_day)
52+
first_day_next_year - first_day
53+
end
54+
55+
# Here we use month to mean ordinal month. Therefore if the calendar
56+
# starts on March 25th, then days in month for March will be seen as
57+
# days if month for month 1.
58+
59+
def days_in_month(month) do
60+
{:error, :unresolved}
61+
end
62+
63+
def days_in_month(year, ordinal_month) do
64+
adjusted_month =
65+
Cldr.Math.amod(ordinal_month + @new_year_starting_month - 1, @months_in_year)
66+
67+
adjusted_year =
68+
if adjusted_month < @new_year_starting_month, do: year + 1, else: year
69+
70+
cond do
71+
# The first month of the year will be short since the year starts
72+
# part way through the month
73+
adjusted_month == @new_year_starting_month ->
74+
days_in_julian_month = Cldr.Calendar.Julian.days_in_month(year, ordinal_month)
75+
days_in_julian_month - @new_year_starting_day
76+
77+
# The last month of the year will be "long" since the first part of the
78+
# first month that is before the start of year will be included
79+
adjusted_month == @last_month_of_year ->
80+
start_of_month =
81+
date_to_iso_days(adjusted_year, adjusted_month, 1)
82+
start_of_next_month =
83+
date_to_iso_days(adjusted_year, @new_year_starting_month, @new_year_starting_day)
84+
start_of_next_month - start_of_month
85+
86+
true ->
87+
Cldr.Calendar.Julian.days_in_month(year, adjusted_month)
88+
end
89+
end
90+
91+
def year(year) do
92+
first_day = date_to_iso_days(year, @new_year_starting_month, @new_year_starting_day)
93+
{:ok, first_date} = Date.new(year, @new_year_starting_month, @new_year_starting_day, __MODULE__)
94+
95+
last_day = date_to_iso_days(year, @new_year_starting_month, @new_year_starting_day) - 1
96+
{year, month, day} = date_from_iso_days(last_day)
97+
{:ok, last_date} = Date.new(year, month, day, __MODULE__)
98+
99+
Date.range(first_date, last_date, 1)
100+
end
101+
102+
def quarter(year, quarter) do
103+
104+
end
105+
106+
def month(year, ordinal_month) do
107+
adjusted_month =
108+
Cldr.Math.amod(ordinal_month + @new_year_starting_month - 1, @months_in_year)
109+
110+
adjusted_year =
111+
if adjusted_month < @new_year_starting_month, do: year + 1, else: year
112+
113+
first_day =
114+
if adjusted_month == @new_year_starting_month, do: @new_year_starting_day, else: 1
115+
116+
{:ok, first} = Date.new(adjusted_year, adjusted_month, first_day, __MODULE__)
117+
first_iso_days = date_to_iso_days(year, adjusted_month, first_day)
118+
days_in_month = days_in_month(year, ordinal_month)
119+
120+
last_iso_days = first_iso_days + days_in_month - 1
121+
{year, month, day} = date_from_iso_days(last_iso_days)
122+
{:ok, last} = Date.new(year, month, day, __MODULE__)
123+
124+
Date.range(first, last, 1)
125+
end
126+
127+
def quarter_of_year(year, month, day) do
128+
month_of_year = month_of_year(year, month, day)
129+
130+
ceil(month_of_year / (@months_in_year / @quarters_in_year))
131+
end
132+
133+
# Returns the ordinal month accounting for a long month 12
134+
def month_of_year(_year, month, day)
135+
when month == @new_year_starting_month and day < @new_year_starting_day do
136+
@months_in_year
137+
end
138+
139+
def month_of_year(_year, month, _day) do
140+
Cldr.Math.amod(month - @new_year_starting_month + 1, @months_in_year)
141+
end
142+
143+
def day_of_year(year, month, day) do
144+
adjusted_year =
145+
if month < @new_year_starting_month, do: year + 1, else: year
146+
147+
first_day = date_to_iso_days(year, @new_year_starting_month, @new_year_starting_day)
148+
this_day = date_to_iso_days(adjusted_year, month, day)
149+
this_day - first_day + 1
150+
end
151+
152+
def calendar_year(year, month, day) when year_rollover(month, day) do
153+
year - 1
154+
end
155+
156+
def calendar_year(year, _month, _day) do
157+
year
158+
end
159+
160+
def related_gregorian_year(year, month, day) do
161+
iso_days = date_to_iso_days(year, month, day)
162+
{year, _month, _day} = Cldr.Calendar.Gregorian.date_from_iso_days(iso_days)
163+
year
164+
end
165+
166+
def extended_year(year, month, day) when year_rollover(month, day) do
167+
year - 1
168+
end
169+
170+
def extended_year(year, month, day) when year_rollover(month, day) do
171+
year
172+
end
173+
174+
def cyclic_year(year, month, day) do
175+
calendar_year(year, month, day)
176+
end
177+
178+
defdelegate valid_date?(year, month, day), to: Cldr.Calendar.Julian
179+
defdelegate leap_year?(year), to: Cldr.Calendar.Julian
180+
defdelegate plus(year, month, day, part, years, options), to: Cldr.Calendar.Julian
181+
defdelegate week(year, week), to: Cldr.Calendar.Julian
182+
defdelegate weeks_in_year(year), to: Cldr.Calendar.Julian
183+
defdelegate months_in_year(year), to: Cldr.Calendar.Julian
184+
defdelegate periods_in_year(year), to: Cldr.Calendar.Julian
185+
defdelegate day_of_week(year, month, day, starts_on), to: Cldr.Calendar.Julian
186+
defdelegate day_of_era(year, month, day), to: Cldr.Calendar.Julian
187+
defdelegate iso_week_of_year(year, month, day), to: Cldr.Calendar.Julian
188+
defdelegate week_of_year(year, month, day), to: Cldr.Calendar.Julian
189+
defdelegate year_of_era(year, month, day), to: Cldr.Calendar.Julian
190+
defdelegate parse_date(date), to: Cldr.Calendar.Julian
191+
defdelegate date_to_string(year, month, day), to: Cldr.Calendar.Julian
192+
defdelegate cldr_calendar_type(), to: Cldr.Calendar.Julian
193+
defdelegate calendar_base(), to: Cldr.Calendar.Julian
194+
defdelegate week_of_month(year, month, day), to: Cldr.Calendar.Julian
195+
defdelegate valid_time?(hour, minute, second, millisecond), to: Cldr.Calendar.Julian
196+
defdelegate time_to_string(hour, minute, second, millisecond), to: Cldr.Calendar.Julian
197+
defdelegate time_to_day_fraction(hour, minute, second, millisecond), to: Cldr.Calendar.Julian
198+
defdelegate time_from_day_fraction(fraction), to: Cldr.Calendar.Julian
199+
defdelegate shift_time(hour, minute, second, millisecond, duration), to: Cldr.Calendar.Julian
200+
defdelegate shift_date(year, month, day, duration), to: Cldr.Calendar.Julian
201+
defdelegate shift_naive_datetime(year, month, day, hour, minute, second, millisecond, duration), to: Cldr.Calendar.Julian
202+
defdelegate iso_days_to_end_of_day(iso_days), to: Cldr.Calendar.Julian
203+
defdelegate iso_days_to_beginning_of_day(iso_days), to: Cldr.Calendar.Julian
204+
defdelegate naive_datetime_from_iso_days(iso_days), to: Cldr.Calendar.Julian
205+
defdelegate parse_utc_datetime(string), to: Cldr.Calendar.Julian
206+
defdelegate parse_time(string), to: Cldr.Calendar.Julian
207+
defdelegate parse_naive_datetime(string), to: Cldr.Calendar.Julian
208+
defdelegate day_rollover_relative_to_midnight_utc, to: Cldr.Calendar.Julian
209+
210+
defdelegate datetime_to_string(year, month, day, hour, minute, second, microsecond, time_zone, zone_abbr, utc_offset, std_offset),
211+
to: Cldr.Calendar.Julian
212+
213+
defdelegate datetime_to_string(year, month, day, hour, minute, second, microsecond, time_zone, zone_abbr, utc_offset, std_offset, format),
214+
to: Cldr.Calendar.Julian
215+
216+
defdelegate naive_datetime_to_string(year, month, day, hour, minute, second, microsecond),
217+
to: Cldr.Calendar.Julian
218+
219+
end
220+
end
221+
end

0 commit comments

Comments
 (0)