25 { unix_time :: float()
35 Timestamp = os:timestamp(),
36 of_timestamp(Timestamp).
38 -spec of_timestamp(erlang:timestamp()) ->
40 of_timestamp({MegasecondsInt, SecondsInt, MicrosecondsInt}) ->
42 Megaseconds = float(MegasecondsInt),
43 Seconds = float(SecondsInt),
44 Microseconds = float(MicrosecondsInt),
45 UnixTime = (Megaseconds * Million) + Seconds + (Microseconds / Million),
46 ?T{unix_time = UnixTime}.
48 -spec to_unix_time(t()) ->
50 to_unix_time(?T{unix_time=UnixTime}) ->
53 -spec of_float(float()) ->
55 of_float(Float) when is_float(Float) ->
56 ?T{unix_time = Float}.
58 -spec to_float(t()) ->
60 to_float(?T{unix_time=Float}) ->
63 -spec of_iso8601(binary()) ->
64 hope_result:t(t(), {unrecognized_as_iso8601, binary()}).
65 of_iso8601(<<Bin/binary>>) ->
66 % We use regexp rather than just simple binary pattern match, because we
67 % also want to validate character ranges, i.e., that components are
70 [ {zoneless, <<"\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d">>}
72 ValidPatternMatchers =
73 [{Tag, make_regexp_bool(RegExp)} || {Tag, RegExp} <- ValidPatterns],
74 case hope_list:first_match(ValidPatternMatchers, Bin)
75 of none -> {error, {unrecognized_as_iso8601, Bin}}
76 ; {some, zoneless} -> {ok, of_iso8601_zoneless(Bin)}
79 -spec of_iso8601_zoneless(binary()) ->
81 of_iso8601_zoneless(<<Bin/binary>>) ->
82 << YearBin:4/binary, "-", MonthBin:2/binary, "-", DayBin:2/binary
84 , HourBin:2/binary, ":", MinBin:2/binary , ":", SecBin:2/binary
86 Year = binary_to_integer(YearBin),
87 Month = binary_to_integer(MonthBin),
88 Day = binary_to_integer(DayBin),
89 Hour = binary_to_integer(HourBin),
90 Min = binary_to_integer(MinBin),
91 Sec = binary_to_integer(SecBin),
92 DateTime = {{Year, Month, Day}, {Hour, Min, Sec}},
93 SecondsGregorian = calendar:datetime_to_gregorian_seconds(DateTime),
94 SecondsFromZeroToUnixEpoch = 62167219200,
95 SecondsUnixEpochInt = SecondsGregorian - SecondsFromZeroToUnixEpoch,
96 SecondsUnixEpoch = float(SecondsUnixEpochInt),
97 of_float(SecondsUnixEpoch).
99 -spec make_regexp_bool(binary()) ->
100 fun((binary()) -> boolean()).
101 make_regexp_bool(<<RegExp/binary>>) ->
102 fun (<<String/binary>>) ->
103 case re:run(String, RegExp)