6
\$\begingroup\$

I want to check if the current time is "close" to 9pm UTC. I have the following code to a.) get "now" and convert it to UTC time and b.) get 9pm utc time.

Based off when I run it, it looks like it's running. However, I usually use scripting languages, and this looks absolutely crazy to me. I don't necessarily want to shorten this in terms of LOC, but I just wanted to check I'm not violating some principle I don't even know about.

#include <iostream>
#include <ctime>

int main() {
    
    // Get the current time in the machine's local time zone
    std::time_t currentTime = std::time(nullptr);

    // Get the time zone difference between local time and UTC (in seconds)
    std::tm* localTime = std::localtime(&currentTime);
    long localTimeZoneOffset = localTime->tm_gmtoff;

    // Adjust the current time to UTC
    std::time_t nowUtcTime = currentTime - localTimeZoneOffset;
    std::tm* utcLocalTime = std::localtime(&nowUtcTime);
    
    // construct 9pm
    std::tm utc9PM = *std::localtime(&nowUtcTime); // deep copy?
    utc9PM.tm_hour = 21; // 9pm utc
    utc9PM.tm_min = 0;
    utc9PM.tm_sec = 0;
    std::time_t ninePmUTC = std::mktime(&utc9PM);

    //ok
    std::cout << "now UTC in seconds since epoch: " << nowUtcTime << std::endl;
    std::cout << "9pm UTC in seconds sinc epoch: " << ninePmUTC << std::endl;
    std::cout << "now in utc calendar time: " << utcLocalTime->tm_hour << ":" << utcLocalTime->tm_min << ":" << utcLocalTime->tm_sec << std::endl;
    std::cout << "9pm utc in calendar time: " << utc9PM.tm_hour <<":" << utc9PM.tm_min <<":" << utc9PM.tm_sec << std::endl;
    
}
\$\endgroup\$
2
  • \$\begingroup\$ That's how you do it in C. \$\endgroup\$ Mar 2 at 1:54
  • \$\begingroup\$ @MartinYork As I mentioned, C has gmtime() in its Standard Library, which returns the UTC time. I would use that instead. \$\endgroup\$
    – Davislor
    Mar 2 at 4:56

1 Answer 1

8
\$\begingroup\$

This is already in the Standard Library. Use std::chrono::utc_clock from <chrono>, and compute the duration:

const auto now = std::chrono::utc_clock::now();
const auto time_of_day = now - std::chrono::floor<std::chrono::days>(now);

An extremely crude example:

#include <chrono>
#include <cstdlib>
#include <iostream>

int main() {
    constexpr auto nine_pm = std::chrono::hours(21);
    const auto now = std::chrono::utc_clock::now();
    const auto time_of_day = now - std::chrono::floor<std::chrono::days>(now);
    const auto in_minutes = std::chrono::duration_cast<std::chrono::minutes>(nine_pm - time_of_day)
        .count();

    if (in_minutes >= 0) {
        std::cout << in_minutes/60 << ':' << in_minutes%60 << " until 21:00 UTC.\n";
    } else {
        const auto minutes_after = -in_minutes;
        std::cout << minutes_after/60 << ':' << minutes_after%60 << " after 21:00 UTC.\n";
    }

    return EXIT_SUCCESS;
}

Or if you stick with <ctime>, use gmtime() to get UTC.

Also, list your headers in alphabetical order, or some other order that’s easy and logical. This will make it much easier to notice missing or duplicated headers.

\$\endgroup\$
2
  • \$\begingroup\$ I didn't state this in the question, but I was mistakenly using 9pm utc to stand for 4PM eastern. After the recent daylight savings time this broke :( \$\endgroup\$
    – Taylor
    Mar 20 at 20:01
  • 1
    \$\begingroup\$ @Taylor Classic XY problem! You want std::chrono::zoned_time, then. \$\endgroup\$
    – Davislor
    Mar 20 at 20:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.