function to calculate seconds to next alarm

Hi

I'm trying to write a function which takes in a current date time (expressed as an epoch) and also takes in an alarm time (expressed as a hour, minute and second) and then calculates the seconds to the next such alarm.

If the current time exceeds the alarm time, it should return the seconds to alarm time on the next day (e.g. if the time is 15 June 2020 at 15:30:22 and the alarm is set at 15:10:22 then the function should return the seconds until 16 June 2020 at 15:30:22). If the time and alarm are the same it should return 0.

I have come up with the below which seems to work but would appreciate any thoughts. If there is an easier way of doing this (using a c library but not an external library), please let me know.

Thanks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

enum timeUnits
{
    SECONDS = 1,
    MINUTES = SECONDS * 60,
    HOURS   = MINUTES * 60,
    DAYS    = HOURS * 24
};

uint32_t calcSecondsToNextAlarm(uint32_t epochSecs, uint32_t alarmHour, uint32_t alarmMinute, uint32_t alarmSecond)
{
    struct tm currentTime;
    time_t currentEpoch = epochSecs;
    gmtime_r ( &currentEpoch, &currentTime ); // convert epoch to date and time
    uint32_t currentHour = currentTime.tm_hour, currentMinute = currentTime.tm_min, currentSecond = currentTime.tm_sec;
    
    // calculate difference between time and alarm in seconds (could be positive or negative)
    int secDiff = ( (alarmHour - currentHour) * HOURS) + ( (alarmMinute - currentMinute) * MINUTES) + ( (alarmSecond - currentSecond) * SECONDS); 
    
    if ( (alarmHour > currentHour) || ( (alarmHour == currentHour) && alarmMinute > currentMinute) || 
         ( (alarmHour == currentHour) && (alarmMinute == currentMinute) && (alarmSecond >= currentSecond) ) )
    {
        return secDiff; // if the alarm is ON or AFTER the time, return the difference
    }
    else return DAYS + secDiff; // if not, offset from seconds in a day
}

int main()
{
   uint32_t currentTimeEpoch = 1610639062; // i.e. 14 Jan 2021  at 15 44 22
   uint32_t secsToNextAlarm = calcSecondsToNextAlarm(currentTimeEpoch, 15, 54, 22);
   
   cout << secsToNextAlarm;
   
   
   return 0;
}
Last edited on
yea you should be able to get the difference directly, subtract, and display it in seconds.

I think this does it if you use the <chrono> time tools? Take a look at those and see if its a better choice for this task.
chrono::duration_cast<chrono::seconds>(end_time - start_time).count()
I don't think chrono has a concept of 'days' though. If it isnt appropriate to your needs, the above may be close. I think it can be simplified a bit from what you have... do you need to talk in calendar days with the user?
Last edited on
thanks, unfortunately i'm working with a platform where std::chrono (and most of standard library) is not available
Since this is a C++ program you don't need the 'struct' in front of tm.

Why don't you store your "epochSecs" as a time_t? time_t is likely to be 64 bits.

It makes more sense to me to use localtime_r instead of gmtime_r
(although now that I think about it I guess it doesn't matter).

You can convert the alarm time to a time_t and use difftime:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <ctime>

long long secsToAlarm(time_t ct, unsigned ah, unsigned am, unsigned as)
{
    const int SecsPerDay = 24 * 60 * 60;
    tm t;
    localtime_r(&ct, &t);
    t.tm_hour = ah;  t.tm_min = am;  t.tm_sec = as;
    long long diff = difftime(mktime(&t), ct);
    return diff < 0 ? diff + SecsPerDay : diff;
}

int main()
{
    tm t {};
    t.tm_year = 2021-1900;  t.tm_mon = 0;  t.tm_mday = 22;
    t.tm_hour = 12;  t.tm_min = 30;  t.tm_sec = 20;
    std::cout << secsToAlarm(mktime(&t), 11, 40, 30) << '\n';
}

Last edited on
Topic archived. No new replies allowed.