herd_datetime.erl 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. -module(herd_datetime).
  2. -export([
  3. now/0, now_micro/0,
  4. datetime_from_db/1,
  5. timestamp_to_datetime/1,
  6. timestamp_to_db_datetime/1,
  7. datetime_to_timestamp/1,
  8. datetime_to_ISO/1,
  9. add_interval/2,
  10. subtract_interval/2
  11. ]).
  12. -type(timestamp() :: integer()). % seconds, 1476882197
  13. -type(timestamp_micro() :: float()). % int part in seconds, 1476882197.233323
  14. %% PostgreSQL datetime format: 2014-12-20 17:38:56.475565
  15. -type(db_datetime() :: {calendar:date(), {0..23, 0..59, float()}}).
  16. -type(time_interval() :: {integer(), week | day | hour | minute | second}).
  17. -define(DAY, 24 * 3600).
  18. %%% module API
  19. -spec now() -> timestamp().
  20. now() ->
  21. os:system_time(seconds).
  22. -spec now_micro() -> timestamp_micro().
  23. now_micro() ->
  24. os:system_time(micro_seconds) * 1.0e-6.
  25. -spec datetime_from_db(db_datetime()) -> calendar:datetime().
  26. datetime_from_db({Date, {Hour, Minute, Second}}) ->
  27. {Date, {Hour, Minute, trunc(Second)}}.
  28. -spec timestamp_to_datetime(timestamp()) -> calendar:datetime().
  29. timestamp_to_datetime(Timestamp) ->
  30. calendar:now_to_universal_time({Timestamp div 1000000, Timestamp rem 1000000, 0}).
  31. -spec timestamp_to_db_datetime(timestamp_micro()) -> db_datetime().
  32. timestamp_to_db_datetime(Timestamp) ->
  33. T = trunc(Timestamp),
  34. MicroSecs = Timestamp - T,
  35. {D, {H, M, S}} = calendar:now_to_universal_time({T div 1000000, T rem 1000000, 0}),
  36. {D, {H, M, S + MicroSecs}}.
  37. -spec datetime_to_timestamp(calendar:datetime()) -> timestamp().
  38. datetime_to_timestamp(DateTime) ->
  39. % 62167219200 == calendar:datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}})
  40. calendar:datetime_to_gregorian_seconds(DateTime) - 62167219200.
  41. -spec datetime_to_ISO(calendar:datetime()) -> string().
  42. datetime_to_ISO({{Year, Month, Day}, {Hour, Minute, Second}}) ->
  43. lists:flatten(
  44. io_lib:format("~4..0b-~2..0b-~2..0bT~2..0b:~2..0b:~2..0b",
  45. [Year, Month, Day, Hour, Minute, trunc(Second)])).
  46. -spec add_interval(calendar:datetime(), time_interval()) -> calendar:datetime().
  47. add_interval(Datetime, {W, week}) ->
  48. add_interval(Datetime, {W * 7 * ?DAY, second});
  49. add_interval(Datetime, {D, day}) ->
  50. add_interval(Datetime, {D * ?DAY, second});
  51. add_interval(Datetime, {H, hour}) ->
  52. add_interval(Datetime, {H * 3600, second});
  53. add_interval(Datetime, {M, minute}) ->
  54. add_interval(Datetime, {M * 60, second});
  55. add_interval(Datetime, {S, second}) ->
  56. T = datetime_to_timestamp(Datetime),
  57. timestamp_to_datetime(T + S).
  58. -spec subtract_interval(calendar:datetime(), time_interval()) -> calendar:datetime().
  59. subtract_interval(Datetime, {M, Type}) ->
  60. add_interval(Datetime, {-M, Type}).