Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -module(iso8601).
- -description('Parse common ISO8601 datetime representations.').
- -export([from/1, to_ts/1, format/1, now/0, now/1]).
- %% 62167219200 == calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}})
- -define(UNIX_EPOCH, 62167219200).
- -type iso8601() :: {DateTime :: calendar:datetime(), MicroSecs :: integer()}.
- -spec to_ts(iso8601()) -> erlang:timestamp().
- to_ts({D, Sub}) ->
- Seconds = calendar:datetime_to_gregorian_seconds(D) - ?UNIX_EPOCH,
- {Seconds div 1000000, Seconds rem 1000000, Sub}.
- -spec format(iso8601()) -> iodata().
- format({D, Sub}) ->
- Seconds = calendar:datetime_to_gregorian_seconds(D) - ?UNIX_EPOCH,
- case Sub of
- 0 -> integer_to_binary(Seconds);
- _ -> [integer_to_binary(Seconds), ".", string:right(integer_to_list(Sub), 6, $0)] end.
- -spec from(string() | binary()) -> iso8601() | {error, {calendar:datetime() | nodatetime, binary()}}.
- from(L) when is_list(L) ->
- from(list_to_binary(L));
- from(<<Y:4/binary, $-, Mo:2/binary, $-, D:2/binary,
- $T,
- H:2/binary, $:, Mi:2/binary, $:, S:2/binary,
- Rest/binary>>) ->
- Dt = {{binary_to_integer(Y), binary_to_integer(Mo), binary_to_integer(D)},
- {binary_to_integer(H), binary_to_integer(Mi), binary_to_integer(S)}},
- subsecond_tz(Dt, Rest);
- from(B) -> {error, {nodatetime, B}}.
- subsecond_tz(D, <<"">>) ->
- {D, 0};
- subsecond_tz(D, <<$Z>>) ->
- {D, 0};
- subsecond_tz(D, <<$+, Ho:2/binary, $:, Mio:2/binary>>) ->
- {tz_offset(D, Ho, Mio), 0};
- subsecond_tz(D, <<$., Sub:3/binary, $Z>>) ->
- {D, binary_to_integer(Sub) * 1000};
- subsecond_tz(D, <<$., Sub:3/binary, $+, Ho:2/binary, $:, Mio:2/binary>>) ->
- {tz_offset(D, Ho, Mio), binary_to_integer(Sub) * 1000};
- subsecond_tz(D, <<$., Sub:6/binary, $Z>>) ->
- {D, binary_to_integer(Sub)};
- subsecond_tz(D, <<$., Sub:6/binary, $+, Ho:2/binary, $:, Mio:2/binary>>) ->
- {tz_offset(D, Ho, Mio), binary_to_integer(Sub)};
- subsecond_tz(D, Rest) ->
- {error, {D, Rest}}.
- tz_offset(D, Ho, Mio) ->
- S1 = calendar:datetime_to_gregorian_seconds(D),
- S2 = (binary_to_integer(Ho)*60 + binary_to_integer(Mio)) * 60,
- calendar:gregorian_seconds_to_datetime(S1 - S2).
- -spec now() -> iso8601().
- now() -> now(os:timestamp()).
- -spec now(erlang:timestamp()) -> iso8601().
- now(Ts = {_, _, Micro}) -> {calendar:now_to_universal_time(Ts), Micro}.
Add Comment
Please, Sign In to add comment