summaryrefslogtreecommitdiff
path: root/elm3/Lib/RDate.elm
blob: 397f7243448847627c1e9f2a929ee91bcf744b03 (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
83
84
-- Utility module and UI widget for handling release dates.
--
-- Release dates are integers with the following format: 0 or yyyymmdd
-- Special values
--   0        -> unknown
--   99999999 -> TBA
--   yyyy9999 -> year known, month & day unknown
--   yyyymm99 -> year & month known, day unknown
--
-- I'm not a big fan of the UI widget. It's functional, but could be much more
-- convenient and intuitive.
module Lib.RDate exposing (..)

import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Date
import Lib.Html exposing (..)
import Lib.Ffi exposing (curYear)


type alias RDate = Int

type alias RDateComp =
  { y : Int
  , m : Int
  , d : Int
  }


expand : RDate -> RDateComp
expand r =
  { y = r // 10000
  , m = modBy 100 (r // 100)
  , d = modBy 100 r
  }


compact : RDateComp -> RDate
compact r = r.y * 10000 + r.m * 100 + r.d


normalize : RDateComp -> RDateComp
normalize r =
       if r.y == 0    then { y = 0,    m = 0,  d = 0  }
  else if r.y == 9999 then { y = 9999, m = 99, d = 99 }
  else if r.m == 99   then { y = r.y,  m = 99, d = 99 }
  else r


type Msg
  = Year String
  | Month String
  | Day String


update : Msg -> RDate -> RDate
update msg ro =
  let r = expand ro
  in compact <| normalize <| case msg of
      Year s  -> { r | y = Maybe.withDefault r.y <| String.toInt s }
      Month s -> { r | m = Maybe.withDefault r.m <| String.toInt s }
      Day s   -> { r | d = Maybe.withDefault r.d <| String.toInt s }


view : RDate -> Bool -> Html Msg
view ro permitUnknown =
  let r = expand ro
      range s = List.range s >> List.map (\n -> (String.fromInt n, String.fromInt n))
      yl = (if permitUnknown then [("0", "Unknown")] else [])
           ++ List.reverse (range 1980 (curYear + 5))
           ++ [("9999", "TBA")]
      ml = ("99", "- month -") :: (range 1 12)
      maxDay = Date.fromCalendarDate r.y (Date.numberToMonth r.m) 1 |> Date.add Date.Months 1 |> Date.add Date.Days -1 |> Date.day
      dl = ("99", "- day -") :: (range 1 maxDay)
  in div []
    [ inputSelect [class "form-control--inline", onInput Year] (String.fromInt r.y) yl
    , if r.y == 0 || r.y == 9999
      then text ""
      else inputSelect [class "form-control--inline", onInput Month] (String.fromInt r.m) ml
    , if r.m == 0 || r.m == 99
      then text ""
      else inputSelect [class "form-control--inline", onInput Day] (String.fromInt r.d) dl
    ]