@@ -53,8 +53,12 @@ defmodule Date do
53
53
@ enforce_keys [ :year , :month , :day ]
54
54
defstruct [ :year , :month , :day , calendar: Calendar.ISO ]
55
55
56
- @ type t :: % Date { year: Calendar . year , month: Calendar . month ,
57
- day: Calendar . day , calendar: Calendar . calendar }
56
+ @ type t :: % Date {
57
+ year: Calendar . year ( ) ,
58
+ month: Calendar . month ( ) ,
59
+ day: Calendar . day ( ) ,
60
+ calendar: Calendar . calendar ( )
61
+ }
58
62
59
63
@ doc """
60
64
Returns a range of dates.
@@ -86,7 +90,7 @@ defmodule Date do
86
90
-366
87
91
"""
88
92
89
- @ spec range ( Calendar . date , Calendar . date ) :: Date.Range . t
93
+ @ spec range ( Calendar . date ( ) , Calendar . date ( ) ) :: Date.Range . t ( )
90
94
def range ( % { calendar: calendar } = first , % { calendar: calendar } = last ) do
91
95
{ first_days , _ } = to_iso_days ( first )
92
96
{ last_days , _ } = to_iso_days ( last )
@@ -95,12 +99,11 @@ defmodule Date do
95
99
first: first ,
96
100
last: last ,
97
101
first_in_iso_days: first_days ,
98
- last_in_iso_days: last_days ,
102
+ last_in_iso_days: last_days
99
103
}
100
104
end
101
105
102
- def range ( % { calendar: _ , year: _ , month: _ , day: _ } ,
103
- % { calendar: _ , year: _ , month: _ , day: _ } ) do
106
+ def range ( % { calendar: _ , year: _ , month: _ , day: _ } , % { calendar: _ , year: _ , month: _ , day: _ } ) do
104
107
raise ArgumentError , "both dates must have matching calendars"
105
108
end
106
109
@@ -114,18 +117,18 @@ defmodule Date do
114
117
true
115
118
116
119
"""
117
- @ spec utc_today ( Calendar . calendar ) :: t
120
+ @ spec utc_today ( Calendar . calendar ( ) ) :: t
118
121
def utc_today ( calendar \\ Calendar.ISO )
119
122
120
123
def utc_today ( Calendar.ISO ) do
121
- { :ok , { year , month , day } , _ , _ } = Calendar.ISO . from_unix ( System . os_time , :native )
124
+ { :ok , { year , month , day } , _ , _ } = Calendar.ISO . from_unix ( System . os_time ( ) , :native )
122
125
% Date { year: year , month: month , day: day }
123
126
end
124
127
125
128
def utc_today ( calendar ) do
126
129
calendar
127
- |> DateTime . utc_now
128
- |> DateTime . to_date
130
+ |> DateTime . utc_now ( )
131
+ |> DateTime . to_date ( )
129
132
end
130
133
131
134
@ doc """
@@ -145,7 +148,7 @@ defmodule Date do
145
148
true
146
149
147
150
"""
148
- @ spec leap_year? ( Calendar . date ) :: boolean ( )
151
+ @ spec leap_year? ( Calendar . date ( ) ) :: boolean ( )
149
152
def leap_year? ( date )
150
153
151
154
def leap_year? ( % { calendar: calendar , year: year } ) do
@@ -165,7 +168,7 @@ defmodule Date do
165
168
29
166
169
167
170
"""
168
- @ spec days_in_month ( Calendar . date ) :: Calendar . day
171
+ @ spec days_in_month ( Calendar . date ( ) ) :: Calendar . day ( )
169
172
def days_in_month ( date )
170
173
171
174
def days_in_month ( % { calendar: calendar , year: year , month: month } ) do
@@ -193,7 +196,7 @@ defmodule Date do
193
196
{:error, :invalid_date}
194
197
195
198
"""
196
- @ spec new ( Calendar . year , Calendar . month , Calendar . day ) :: { :ok , t } | { :error , atom }
199
+ @ spec new ( Calendar . year ( ) , Calendar . month ( ) , Calendar . day ( ) ) :: { :ok , t } | { :error , atom }
197
200
def new ( year , month , day , calendar \\ Calendar.ISO ) do
198
201
if calendar . valid_date? ( year , month , day ) do
199
202
{ :ok , % Date { year: year , month: month , day: day , calendar: calendar } }
@@ -213,7 +216,7 @@ defmodule Date do
213
216
"2000-02-28"
214
217
215
218
"""
216
- @ spec to_string ( Calendar . date ) :: String . t
219
+ @ spec to_string ( Calendar . date ( ) ) :: String . t ( )
217
220
def to_string ( date )
218
221
219
222
def to_string ( % { calendar: calendar , year: year , month: month , day: day } ) do
@@ -236,15 +239,14 @@ defmodule Date do
236
239
{:error, :invalid_date}
237
240
238
241
"""
239
- @ spec from_iso8601 ( String . t ) :: { :ok , t } | { :error , atom }
242
+ @ spec from_iso8601 ( String . t ( ) ) :: { :ok , t } | { :error , atom }
240
243
def from_iso8601 ( string , calendar \\ Calendar.ISO )
241
244
242
245
def from_iso8601 ( << year :: 4 - bytes , ?- , month :: 2 - bytes , ?- , day :: 2 - bytes >> , calendar ) do
243
246
with { year , "" } <- Integer . parse ( year ) ,
244
247
{ month , "" } <- Integer . parse ( month ) ,
245
248
{ day , "" } <- Integer . parse ( day ) do
246
- with { :ok , date } <- new ( year , month , day , Calendar.ISO ) ,
247
- do: convert ( date , calendar )
249
+ with { :ok , date } <- new ( year , month , day , Calendar.ISO ) , do: convert ( date , calendar )
248
250
else
249
251
_ -> { :error , :invalid_format }
250
252
end
@@ -267,13 +269,14 @@ defmodule Date do
267
269
iex> Date.from_iso8601!("2015:01:23")
268
270
** (ArgumentError) cannot parse "2015:01:23" as date, reason: :invalid_format
269
271
"""
270
- @ spec from_iso8601! ( String . t ) :: t
272
+ @ spec from_iso8601! ( String . t ( ) ) :: t
271
273
def from_iso8601! ( string , calendar \\ Calendar.ISO ) do
272
274
case from_iso8601 ( string , calendar ) do
273
275
{ :ok , value } ->
274
276
value
277
+
275
278
{ :error , reason } ->
276
- raise ArgumentError , "cannot parse #{ inspect string } as date, reason: #{ inspect reason } "
279
+ raise ArgumentError , "cannot parse #{ inspect ( string ) } as date, reason: #{ inspect ( reason ) } "
277
280
end
278
281
end
279
282
@@ -300,7 +303,7 @@ defmodule Date do
300
303
"2000-02-28"
301
304
302
305
"""
303
- @ spec to_iso8601 ( Calendar . date , :extended | :basic ) :: String . t
306
+ @ spec to_iso8601 ( Calendar . date ( ) , :extended | :basic ) :: String . t ( )
304
307
def to_iso8601 ( date , format \\ :extended ) when format in [ :basic , :extended ] do
305
308
% { year: year , month: month , day: day } = convert! ( date , Calendar.ISO )
306
309
Calendar.ISO . date_to_iso8601 ( year , month , day , format )
@@ -322,7 +325,7 @@ defmodule Date do
322
325
{2000, 1, 1}
323
326
324
327
"""
325
- @ spec to_erl ( Calendar . date ) :: :calendar . date
328
+ @ spec to_erl ( Calendar . date ( ) ) :: :calendar . date ( )
326
329
def to_erl ( date ) do
327
330
% { year: year , month: month , day: day } = convert! ( date , Calendar.ISO )
328
331
{ year , month , day }
@@ -343,12 +346,11 @@ defmodule Date do
343
346
{:error, :invalid_date}
344
347
345
348
"""
346
- @ spec from_erl ( :calendar . date ) :: { :ok , t } | { :error , atom }
349
+ @ spec from_erl ( :calendar . date ( ) ) :: { :ok , t } | { :error , atom }
347
350
def from_erl ( tuple , calendar \\ Calendar.ISO )
348
351
349
352
def from_erl ( { year , month , day } , calendar ) do
350
- with { :ok , date } <- new ( year , month , day , Calendar.ISO ) ,
351
- do: convert ( date , calendar )
353
+ with { :ok , date } <- new ( year , month , day , Calendar.ISO ) , do: convert ( date , calendar )
352
354
end
353
355
354
356
@ doc """
@@ -362,13 +364,15 @@ defmodule Date do
362
364
** (ArgumentError) cannot convert {2000, 13, 1} to date, reason: :invalid_date
363
365
364
366
"""
365
- @ spec from_erl! ( :calendar . date ) :: t
367
+ @ spec from_erl! ( :calendar . date ( ) ) :: t
366
368
def from_erl! ( tuple ) do
367
369
case from_erl ( tuple ) do
368
370
{ :ok , value } ->
369
371
value
372
+
370
373
{ :error , reason } ->
371
- raise ArgumentError , "cannot convert #{ inspect tuple } to date, reason: #{ inspect reason } "
374
+ raise ArgumentError ,
375
+ "cannot convert #{ inspect ( tuple ) } to date, reason: #{ inspect ( reason ) } "
372
376
end
373
377
end
374
378
@@ -395,15 +399,20 @@ defmodule Date do
395
399
:eq
396
400
397
401
"""
398
- @ spec compare ( Calendar . date , Calendar . date ) :: :lt | :eq | :gt
399
- def compare ( % { calendar: calendar , year: year1 , month: month1 , day: day1 } ,
400
- % { calendar: calendar , year: year2 , month: month2 , day: day2 } ) do
402
+ @ spec compare ( Calendar . date ( ) , Calendar . date ( ) ) :: :lt | :eq | :gt
403
+ def compare ( % { calendar: calendar , year: year1 , month: month1 , day: day1 } , % {
404
+ calendar: calendar ,
405
+ year: year2 ,
406
+ month: month2 ,
407
+ day: day2
408
+ } ) do
401
409
case { { year1 , month1 , day1 } , { year2 , month2 , day2 } } do
402
410
{ first , second } when first > second -> :gt
403
411
{ first , second } when first < second -> :lt
404
412
_ -> :eq
405
413
end
406
414
end
415
+
407
416
def compare ( date1 , date2 ) do
408
417
if Calendar . compatible_calendars? ( date1 . calendar , date2 . calendar ) do
409
418
case { to_iso_days ( date1 ) , to_iso_days ( date2 ) } do
@@ -413,7 +422,7 @@ defmodule Date do
413
422
end
414
423
else
415
424
raise ArgumentError , """
416
- cannot compare #{ inspect date1 } with #{ inspect date2 } .
425
+ cannot compare #{ inspect ( date1 ) } with #{ inspect ( date2 ) } .
417
426
418
427
This comparison would be ambiguous as their calendars have incompatible day rollover moments.
419
428
Specify an exact time of day (using `DateTime`s) to resolve this ambiguity
@@ -439,16 +448,19 @@ defmodule Date do
439
448
{:ok, %Date{calendar: Calendar.Holocene, year: 12000, month: 1, day: 1}}
440
449
441
450
"""
442
- @ spec convert ( Calendar . date , Calendar . calendar ) :: { :ok , t } | { :error , :incompatible_calendars }
451
+ @ spec convert ( Calendar . date ( ) , Calendar . calendar ( ) ) ::
452
+ { :ok , t } | { :error , :incompatible_calendars }
443
453
def convert ( % { calendar: calendar , year: year , month: month , day: day } , calendar ) do
444
454
{ :ok , % Date { calendar: calendar , year: year , month: month , day: day } }
445
455
end
456
+
446
457
def convert ( % { calendar: calendar } = date , target_calendar ) do
447
458
if Calendar . compatible_calendars? ( calendar , target_calendar ) do
448
459
result_date =
449
460
date
450
461
|> to_iso_days ( )
451
462
|> from_iso_days ( target_calendar )
463
+
452
464
{ :ok , result_date }
453
465
else
454
466
{ :error , :incompatible_calendars }
@@ -469,13 +481,17 @@ defmodule Date do
469
481
%Date{calendar: Calendar.Holocene, year: 12000, month: 1, day: 1}
470
482
471
483
"""
472
- @ spec convert! ( Calendar . date , Calendar . calendar ) :: t
484
+ @ spec convert! ( Calendar . date ( ) , Calendar . calendar ( ) ) :: t
473
485
def convert! ( date , calendar ) do
474
486
case convert ( date , calendar ) do
475
487
{ :ok , value } ->
476
488
value
489
+
477
490
{ :error , reason } ->
478
- raise ArgumentError , "cannot convert #{ inspect date } to target calendar #{ inspect calendar } , reason: #{ inspect reason } "
491
+ raise ArgumentError ,
492
+ "cannot convert #{ inspect ( date ) } to target calendar #{ inspect ( calendar ) } , reason: #{
493
+ inspect ( reason )
494
+ } "
479
495
end
480
496
end
481
497
@@ -496,7 +512,7 @@ defmodule Date do
496
512
~D[2000-01-03]
497
513
498
514
"""
499
- @ spec add ( Calendar . date , integer ( ) ) :: t
515
+ @ spec add ( Calendar . date ( ) , integer ( ) ) :: t
500
516
def add ( % { calendar: calendar } = date , days ) do
501
517
{ iso_days , fraction } = to_iso_days ( date )
502
518
from_iso_days ( { iso_days + days , fraction } , calendar )
@@ -520,9 +536,13 @@ defmodule Date do
520
536
-2
521
537
522
538
"""
523
- @ spec diff ( Calendar . date , Calendar . date ) :: integer
524
- def diff ( % { calendar: Calendar.ISO , year: year1 , month: month1 , day: day1 } ,
525
- % { calendar: Calendar.ISO , year: year2 , month: month2 , day: day2 } ) do
539
+ @ spec diff ( Calendar . date ( ) , Calendar . date ( ) ) :: integer
540
+ def diff ( % { calendar: Calendar.ISO , year: year1 , month: month1 , day: day1 } , % {
541
+ calendar: Calendar.ISO ,
542
+ year: year2 ,
543
+ month: month2 ,
544
+ day: day2
545
+ } ) do
526
546
Calendar.ISO . date_to_iso_days ( year1 , month1 , day1 ) -
527
547
Calendar.ISO . date_to_iso_days ( year2 , month2 , day2 )
528
548
end
@@ -533,13 +553,15 @@ defmodule Date do
533
553
{ days2 , _ } = to_iso_days ( date2 )
534
554
days1 - days2
535
555
else
536
- raise ArgumentError , "cannot calculate the difference between #{ inspect date1 } and #{ inspect date2 } because their calendars are not compatible and thus the result would be ambiguous"
556
+ raise ArgumentError ,
557
+ "cannot calculate the difference between #{ inspect ( date1 ) } and #{ inspect ( date2 ) } because their calendars are not compatible and thus the result would be ambiguous"
537
558
end
538
559
end
539
560
540
561
defp to_iso_days ( % { calendar: Calendar.ISO , year: year , month: month , day: day } ) do
541
- { Calendar.ISO . date_to_iso_days ( year , month , day ) , { 0 , 86400000000 } }
562
+ { Calendar.ISO . date_to_iso_days ( year , month , day ) , { 0 , 86_400_000_000 } }
542
563
end
564
+
543
565
defp to_iso_days ( % { calendar: calendar , year: year , month: month , day: day } ) do
544
566
calendar . naive_datetime_to_iso_days ( year , month , day , 0 , 0 , 0 , { 0 , 0 } )
545
567
end
@@ -548,6 +570,7 @@ defmodule Date do
548
570
{ year , month , day } = Calendar.ISO . date_from_iso_days ( days )
549
571
% Date { year: year , month: month , day: day , calendar: Calendar.ISO }
550
572
end
573
+
551
574
defp from_iso_days ( iso_days , target_calendar ) do
552
575
{ year , month , day , _ , _ , _ , _ } = target_calendar . naive_datetime_from_iso_days ( iso_days )
553
576
% Date { year: year , month: month , day: day , calendar: target_calendar }
@@ -570,7 +593,7 @@ defmodule Date do
570
593
2
571
594
572
595
"""
573
- @ spec day_of_week ( Calendar . date ) :: non_neg_integer ( )
596
+ @ spec day_of_week ( Calendar . date ( ) ) :: non_neg_integer ( )
574
597
def day_of_week ( date )
575
598
576
599
def day_of_week ( % { calendar: calendar , year: year , month: month , day: day } ) do
0 commit comments