user997112
user997112

Reputation: 30635

Number of seconds since midnight

I wrote the below code to get the number of seconds since midnight.

However, I'm not great with the C time date structs. Is there a simpler way of doing this using a standard C++ library?

// Get today's date
time_t aTime = time(NULL);

// Set the time to midnight
struct tm* tm = localtime(&aTime);
tm->tm_sec = 0;
tm->tm_min = 0;
tm->tm_hour = 0;
tm->tm_isdst = -1;
time_t midnight = mktime(tm);

// Create object representing now
struct timespec now;
clock_gettime(CLOCK_REALTIME, &now);

// Number of seconds (now) since Epoch
const uint64_t nowSecsSinceEpoch = now.tv_sec;

// Number of seconds (now) since midnight = seconds (now) since Epoch minus seconds (at midnight) since Epoch
const uint64_t nowSecsSinceMidnight = nowSecsSinceEpoch - midnight;

Upvotes: 10

Views: 3461

Answers (1)

Howard Hinnant
Howard Hinnant

Reputation: 219245

It depends on if you mean time since midnight UTC, or time since midnight local time, or perhaps in some non-local, far away time zone.

This is also made much easier in C++20. But there exists a preview of the C++20 parts of the <chrono> library that can be used with C++11-17.

Time since midnight UTC

#include <chrono>
#include <iostream>

int
main()
{
    using namespace std;
    using namespace std::chrono;

    auto now = system_clock::now();
    auto today = floor<days>(now);
    auto tod = duration_cast<seconds>(now - today);
}

This simply gets the current time (UTC), truncates it to a days-precision time_point, and then subtracts the two and truncates that difference to seconds precision.

Time since local midnight

#include <chrono>
#include <iostream>

int
main()
{
    using namespace std;
    using namespace std::chrono;

    auto now = current_zone()->to_local(system_clock::now());
    auto today = floor<days>(now);
    auto tod = duration_cast<seconds>(now - today);
}

This version finds your computer's currently set local time zone, and then gets the current local time via the time_zone's to_local() member function. And then proceeds as before.

Time since some other midnight

#include <chrono>
#include <iostream>

int
main()
{
    using namespace std;
    using namespace std::chrono;

    auto now = locate_zone("Australia/Sydney")->to_local(system_clock::now());
    auto today = floor<days>(now);
    auto tod = duration_cast<seconds>(now - today);
}

Finally, this version finds the time_zone associated with Sydney Australia, and then uses that time zone and proceeds as before.

The C++20 preview <chrono> library is free and open-source. It puts everything in namespace date, and in two headers (and one source):

  • date.h: A header-only library that will do the UTC part, but has no time zone support.

  • tz.h: For the time zone support. This requires some installation.

Upvotes: 7

Related Questions