aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/program/aedifex/artifact/time/date.lux
blob: f6b8ae5a99fe77125a13cf17eb1ef9c22ad803c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(.module:
  [library
   [lux #*
    [abstract
     [monad (#+ do)]
     [equivalence (#+ Equivalence)]]
    [control
     ["." try (#+ Try)]
     ["." exception (#+ exception:)]
     ["<>" parser
      ["<.>" text (#+ Parser)]]]
    [data
     [text
      ["%" format]]]
    [math
     [number
      ["n" nat]
      ["i" int]]]
    [time
     ["." date ("#\." equivalence)]
     ["." year]
     ["." month]]
    [type
     abstract]]])

(def: #export (pad value)
  (-> Nat Text)
  (if (n.< 10 value)
    (%.format "0" (%.nat value))
    (%.nat value)))

(def: min_year +1,000)
(def: max_year +9,999)

(exception: #export (year_is_out_of_range {year year.Year})
  (exception.report
   ["Minimum" (%.int ..min_year)]
   ["Maximum" (%.int ..max_year)]
   ["Year" (%.int (year.value year))]))

(abstract: #export Date
  date.Date

  (def: #export epoch
    Date
    (:abstraction date.epoch))

  (def: #export (date raw)
    (-> date.Date (Try Date))
    (let [year (|> raw date.year year.value)]
      (if (and (i.>= ..min_year year)
               (i.<= ..max_year year))
        (#try.Success (:abstraction raw))
        (exception.throw ..year_is_out_of_range [(date.year raw)]))))

  (def: #export value
    (-> Date date.Date)
    (|>> :representation))

  (implementation: #export equivalence
    (Equivalence Date)

    (def: (= reference subject)
      (date\= (:representation reference)
              (:representation subject))))

  (def: #export (format value)
    (%.Format Date)
    (%.format (|> value :representation date.year year.value .nat %.nat)
              (|> value :representation date.month month.number ..pad)
              (|> value :representation date.day_of_month ..pad)))

  (def: #export parser
    (Parser Date)
    (do <>.monad
      [year (<>.codec n.decimal (<text>.exactly 4 <text>.decimal))
       year (<>.lift (year.year (.int year)))
       month (<>.codec n.decimal (<text>.exactly 2 <text>.decimal))
       month (<>.lift (month.by_number month))
       day_of_month (<>.codec n.decimal (<text>.exactly 2 <text>.decimal))
       date (<>.lift (date.date year month day_of_month))]
      (wrap (:abstraction date)))))