Grant Winney
Grant Winney

Reputation: 66489

How do I add xx seconds, minutes, or hours to a DateTime structure?

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

Answers (3)

Grant Winney
Grant Winney

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

zxq9
zxq9

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

P_A
P_A

Reputation: 1818

Also you can use special time managment libs such as qdate.

Example usage, adding a year, month and minute, and removing 3 days and 5 hours.

NewDate = qdate:add_date({{1, 2, -3}, {-5, 1, 0}}, {{2018, 8, 16}, {11, 0, 1}}).

Upvotes: 3

Related Questions