Convert Epoch Seconds to DMYHMS

From Erlang Community

(Difference between revisions)
Revision as of 13:29, 24 September 2006 (edit)
Ayrnieu (Talk | contribs)
(would this be preferable?)
← Previous diff
Current revision (14:15, 9 August 2008) (edit) (undo)
Thomas (Talk | contribs)
(Added a symmetric solution that returns values)
 
(4 intermediate revisions not shown.)
Line 14: Line 14:
{{34,4,26},{23,34,18}} {{34,4,26},{23,34,18}}
4> io:fwrite("Today's Date is ~2B/~2B/~4..0B ~2B:~2.10.0B:~2.10.0B\n", 4> io:fwrite("Today's Date is ~2B/~2B/~4..0B ~2B:~2.10.0B:~2.10.0B\n",
-4> [Month, Day, Year, Hour, Min, Sec]).+ [Month, Day, Year, Hour, Min, Sec]).
Today's Date is 4/26/0034 23:34:18 Today's Date is 4/26/0034 23:34:18
ok ok
Line 26: Line 26:
6> io_lib:fread("~4d-~2d-~2dT~2d:~2d:~2d-~4d", Some_Date_String). 6> io_lib:fread("~4d-~2d-~2dT~2d:~2d:~2d-~4d", Some_Date_String).
{ok,[2004,4,26,18,26,18,500],[]} {ok,[2004,4,26,18,26,18,500],[]}
 +</code>
 +
 +
 +== Symmetric conversion ==
 +
 +[[Author:Thomas Arts]]
 +
 +The above conversion writes directly to the console, but sometimes, one would like an approach in which functions return the converted string and given a string, seconds are returned:
 +<code>
 +epoch_to_mdyhms(Seconds) -> DateString
 +mdyhms_to_epoch(DateString) -> Seconds
 +</code>
 +When creating such a solution, symmetry is an important property to strive after. Intuitively, one expects the following property to hold for conversions
 +<code>
 +prop_epoch_mdyhms_identity() ->
 + ?FORALL(Seconds,seconds(),
 + mdyhms_to_epoch(epoch_to_mdyhms(Seconds)) == Seconds).
 +
 +seconds() ->
 + ?LET(I,largeint(),abs(I)).
 +</code>
 +However, that property clearly is violated in the code above, which we can observe by manually looking at the output produced.
 +
 +A symmetric and testable solution is given by:
 +<code>
 +epoch_to_mdyhms(Seconds) ->
 + {{Year, Month, Day}, {Hour, Min, Sec}} =
 + calendar:gregorian_seconds_to_datetime(Seconds),
 + lists:flatten(
 + io_lib:fwrite("~2B/~2B/~4..0B ~2B:~2.10.0B:~2.10.0B",
 + [Month, Day, Year, Hour, Min, Sec])).
 +
 +
 +mdyhms_to_epoch(DateString) ->
 + {ok,[Month, Day, Year, Hour, Min, Sec],_} =
 + io_lib:fread("~d/~d/~d ~d:~d:~d", DateString),
 + calendar:datetime_to_gregorian_seconds({{Year,Month,Day},{Hour,Min,Sec}}).
</code> </code>
[[Category:CookBook]][[Category:DateTimeRecipes]] [[Category:CookBook]][[Category:DateTimeRecipes]]

Current revision

[edit] Problem

You have a date and time in Erlang Epoch seconds (i.e., Gregorian calendar year 0 seconds), and you want to calculate the individual DMYHMS values from it.

[edit] Solution

In recipe TimeToday we did exactly this but only for the current date. How about if we wanted to get the date, and time (DMYHMS) associated to a particular number of seconds? Once more we would use gre.

1> Seconds = 1083022458.
1083022458
2> DateTime = calendar:gregorian_seconds_to_datetime(Seconds).
{{34,4,26},{23,34,18}}
3> {{Year, Month, Day}, {Hour, Min, Sec}} = DateTime.
{{34,4,26},{23,34,18}}
4> io:fwrite("Today's Date is ~2B/~2B/~4..0B ~2B:~2.10.0B:~2.10.0B\n",
              [Month, Day, Year, Hour, Min, Sec]).
Today's Date is  4/26/0034 23:34:18
ok                       

In recipe TimeToday we discussed how to convert a date structure to a string. Convert in the opposite direction is also possible, and useful. Unfortunately, there is not a lot of built-in Erlang plumbing to do so. However, if we are very sure of the format we can easily extract the data we need using Erlang's ever-helpful io and io_lib modules:

5> Some_Date_String = "2004-04-26T18:26:18-0500".
"2004-04-26T18:26:18-0500".
6> {ok, [YYY,MMM,DD,HH,MM,SS,ZZ],_} = 
6> io_lib:fread("~4d-~2d-~2dT~2d:~2d:~2d-~4d", Some_Date_String).
{ok,[2004,4,26,18,26,18,500],[]}


[edit] Symmetric conversion

Author:Thomas Arts

The above conversion writes directly to the console, but sometimes, one would like an approach in which functions return the converted string and given a string, seconds are returned:

epoch_to_mdyhms(Seconds) -> DateString
mdyhms_to_epoch(DateString) -> Seconds

When creating such a solution, symmetry is an important property to strive after. Intuitively, one expects the following property to hold for conversions

prop_epoch_mdyhms_identity() ->
    ?FORALL(Seconds,seconds(),
            mdyhms_to_epoch(epoch_to_mdyhms(Seconds)) == Seconds).

seconds() ->
    ?LET(I,largeint(),abs(I)).

However, that property clearly is violated in the code above, which we can observe by manually looking at the output produced.

A symmetric and testable solution is given by:

epoch_to_mdyhms(Seconds) -> 
    {{Year, Month, Day}, {Hour, Min, Sec}} =
        calendar:gregorian_seconds_to_datetime(Seconds),
    lists:flatten(
	io_lib:fwrite("~2B/~2B/~4..0B ~2B:~2.10.0B:~2.10.0B",
                      [Month, Day, Year, Hour, Min, Sec])).


mdyhms_to_epoch(DateString) ->
	{ok,[Month, Day, Year, Hour, Min, Sec],_} = 
	   io_lib:fread("~d/~d/~d ~d:~d:~d", DateString),
        calendar:datetime_to_gregorian_seconds({{Year,Month,Day},{Hour,Min,Sec}}).
Erlang/OTP Projects
Personal tools