Reputation: 66489
I'd like to add a certain period of time to an existing DateTime
value (in {{Y,M,D},{H,m,s}}
format), but don't see a function (such as in the Calendar
module) that allows me to manipulate a DateTime
value directly.
How can I add (for example) 10 seconds, 10 minutes, or 10 hours to such a value?
Upvotes: 3
Views: 1280
Reputation: 66489
You can use the Calendar
module to convert the DateTime
to seconds, which makes it easier to add the desired seconds, minutes, hours, etc.
For example, to add 10 seconds:
Date = {{2018,8,14},{13,10,25}}.
DateInSeconds = calendar:datetime_to_gregorian_seconds(Date). % 63701471425
NewDateInSeconds = DateInSeconds + 10. % 63701471435
calendar:gregorian_seconds_to_datetime(NewDateInSeconds). % {{2018,8,14},{13,10,35}}
For 10 minutes or 10 hours, just perform a little math:
Date = {{2018,8,14},{13,10,25}}.
DateInSeconds = calendar:datetime_to_gregorian_seconds(Date). % 63701471425
NewDateInSeconds = DateInSeconds + (10 * 60 * 60). % 63701507425 (10 hours)
calendar:gregorian_seconds_to_datetime(NewDateInSeconds). % {{2018,8,14},{23,10,25}}
To make life easier, you could even create a function for this, to add additional time to (or subtract time from) an existing DateTime
:
-type datetime() :: {{non_neg_integer(), pos_integer(), pos_integer()},
{non_neg_integer(), non_neg_integer(), non_neg_integer()}}.
-type timespan() :: {integer(), integer(), integer()}.
-spec add_time_to_datetime(datetime(), timespan()) -> datetime().
add_time_to_datetime(Date, {Hour, Min, Sec}) ->
DateInSeconds = calendar:datetime_to_gregorian_seconds(Date),
NewDateInSeconds = DateInSeconds + (Hour * 60 * 60) + (Min * 60) + Sec,
calendar:gregorian_seconds_to_datetime(NewDateInSeconds).
Upvotes: 4
Reputation: 13164
If you want to accept two datetime structures and subtract the second from the first, conversion to Gregorian seconds, performing the subtraction, and then reconversion is the most common way:
sub_datetime(DT1, DT2) ->
Seconds1 = calendar:datetime_to_gregorian_seconds(DT1),
Seconds2 = calendar:datetime_to_gregorian_seconds(DT2),
Diff = Seconds1 - Seconds2,
calendar:gregorian_seconds_to_datetime(Diff).
Addition is the same thing, just with the opposite operation (and of course this becomes commutative as well).
add_datetime(DT1, DT2) ->
Seconds1 = calendar:datetime_to_gregorian_seconds(DT1),
Seconds2 = calendar:datetime_to_gregorian_seconds(DT2),
Sum = Seconds1 + Seconds2,
calendar:gregorian_seconds_to_datetime(Sum).
This works in all situations and doesn't require deciphering anything or math other than the single operation (on your behalf, anyway). You notice, of course, the opportunity here for pulling the one unique part of these two functions out -- but that sort of DRY isn't really called for with just two functions. Meh.
If you want a "list-of-args friendly" sort of way to call the above:
add_time(Years, Months, Days, Hours, Minutes, Seconds, Target) ->
AddedTime = {{Years, Months, Days}, {Hours, Minutes, Seconds}},
add_datetime(AddedTime, Target).
Upvotes: 2