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