Guest User

Untitled

a guest
Feb 18th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.29 KB | None | 0 0
  1. -module(iso8601).
  2. -description('Parse common ISO8601 datetime representations.').
  3. -export([from/1, to_ts/1, format/1, now/0, now/1]).
  4.  
  5. %% 62167219200 == calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}})
  6. -define(UNIX_EPOCH, 62167219200).
  7.  
  8. -type iso8601() :: {DateTime :: calendar:datetime(), MicroSecs :: integer()}.
  9.  
  10. -spec to_ts(iso8601()) -> erlang:timestamp().
  11. to_ts({D, Sub}) ->
  12. Seconds = calendar:datetime_to_gregorian_seconds(D) - ?UNIX_EPOCH,
  13. {Seconds div 1000000, Seconds rem 1000000, Sub}.
  14.  
  15. -spec format(iso8601()) -> iodata().
  16. format({D, Sub}) ->
  17. Seconds = calendar:datetime_to_gregorian_seconds(D) - ?UNIX_EPOCH,
  18. case Sub of
  19. 0 -> integer_to_binary(Seconds);
  20. _ -> [integer_to_binary(Seconds), ".", string:right(integer_to_list(Sub), 6, $0)] end.
  21.  
  22. -spec from(string() | binary()) -> iso8601() | {error, {calendar:datetime() | nodatetime, binary()}}.
  23. from(L) when is_list(L) ->
  24. from(list_to_binary(L));
  25. from(<<Y:4/binary, $-, Mo:2/binary, $-, D:2/binary,
  26. $T,
  27. H:2/binary, $:, Mi:2/binary, $:, S:2/binary,
  28. Rest/binary>>) ->
  29. Dt = {{binary_to_integer(Y), binary_to_integer(Mo), binary_to_integer(D)},
  30. {binary_to_integer(H), binary_to_integer(Mi), binary_to_integer(S)}},
  31. subsecond_tz(Dt, Rest);
  32. from(B) -> {error, {nodatetime, B}}.
  33.  
  34. subsecond_tz(D, <<"">>) ->
  35. {D, 0};
  36. subsecond_tz(D, <<$Z>>) ->
  37. {D, 0};
  38. subsecond_tz(D, <<$+, Ho:2/binary, $:, Mio:2/binary>>) ->
  39. {tz_offset(D, Ho, Mio), 0};
  40. subsecond_tz(D, <<$., Sub:3/binary, $Z>>) ->
  41. {D, binary_to_integer(Sub) * 1000};
  42. subsecond_tz(D, <<$., Sub:3/binary, $+, Ho:2/binary, $:, Mio:2/binary>>) ->
  43. {tz_offset(D, Ho, Mio), binary_to_integer(Sub) * 1000};
  44. subsecond_tz(D, <<$., Sub:6/binary, $Z>>) ->
  45. {D, binary_to_integer(Sub)};
  46. subsecond_tz(D, <<$., Sub:6/binary, $+, Ho:2/binary, $:, Mio:2/binary>>) ->
  47. {tz_offset(D, Ho, Mio), binary_to_integer(Sub)};
  48. subsecond_tz(D, Rest) ->
  49. {error, {D, Rest}}.
  50.  
  51. tz_offset(D, Ho, Mio) ->
  52. S1 = calendar:datetime_to_gregorian_seconds(D),
  53. S2 = (binary_to_integer(Ho)*60 + binary_to_integer(Mio)) * 60,
  54. calendar:gregorian_seconds_to_datetime(S1 - S2).
  55.  
  56.  
  57. -spec now() -> iso8601().
  58. now() -> now(os:timestamp()).
  59.  
  60. -spec now(erlang:timestamp()) -> iso8601().
  61. now(Ts = {_, _, Micro}) -> {calendar:now_to_universal_time(Ts), Micro}.
Add Comment
Please, Sign In to add comment