Potion
Potion

Reputation: 946

Convert Epoch Milliseconds to UTC Date and Time using c++

I can get the current epoch time in milliseconds:

#include <chrono>
#include <cstdint>
#include <iostream>
#include <ctime>

uint64_t timeSinceEpochMillisec() {
  using namespace std::chrono;
  return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}

int main() {
  std::cout << timeSinceEpochMillisec() << std::endl;
  return 0;
}

This will output: 1597436329290.

I have a snippet of code which uses epoch time in seconds that works fine. How can I use timeSinceEpochMillisec() to format the date and time using strftime?

std::time_t epoch_timestamp = std::time(nullptr);
char buf[80];

std::tm *ts = std::gmtime(&epoch_timestamp);
strftime(buf, sizeof(buf), "%m/%d/%Y %H:%M:%S", ts);
std::cout << buf << std::endl;

outputs:

1597437386198
08/14/2020/ 20:36:26

Upvotes: 1

Views: 7484

Answers (1)

darcamo
darcamo

Reputation: 3503

Unfortunately, the chrono library only deals with time, and not dates. It seems things will change in C++20, but for now we have to work with functions and types from the ctime library.

That is, once you get the current time with SomeClock::now() you can use to_time_t to convert it to a std::time_t, from the ctime library. After that there is no more chrono library involved, only ctime library.

See this and this stackoverflow questions.

A std::time_t is usually just the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC. Your timeSinceEpochMillisec function is similar but it gives the number of milliseconds instead. If you divide its output by 1000 and get the integer result you probably will have the same number as std::time(nullptr), but that might be implementation dependent (std::time_t might be defined diferently).

#include <chrono>
#include <cstdint>
#include <ctime>
#include <iostream>

using Clock = std::chrono::system_clock;

uint64_t timeSinceEpochMillisec() {
    using namespace std::chrono;
    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}

int main() {
    auto now = Clock::now();

    // time_t comes from the C library and "it is generally implemented as an
    // integral value representing the number of seconds elapsed since 00:00
    // hours, Jan 1, 1970 UTC"
    // http://www.cplusplus.com/reference/ctime/time_t/
    auto now_in_time_t = Clock::to_time_t(now);

    // let's compare what we get with the current time converted to time_t and
    // your timeSinceEpochMillisec function
    std::cout << "Your functin: " << timeSinceEpochMillisec() << std::endl;
    std::cout << "time_t: " << now_in_time_t << std::endl;

    // Now let's work with dates. First we convert the current time to a date

    // Use std::localtime to convert the time_t to a "date", whose type is "tm*", where "tm" is a struct
    // Note that I'm using std::localtime instead of std::gmtime to get the date
    // in my local timezone. The std::gmtime gets the date in UTC.

    // https://en.cppreference.com/w/cpp/chrono/c/localtime
    auto now_as_tm_date = std::localtime(&now_in_time_t);

    // Now we can wuery the date struct for individual data
    // tm_year gives the number of years since 1900
    std::cout << "Current year is: " << now_as_tm_date->tm_year + 1900 << std::endl;
    // See http://www.cplusplus.com/reference/ctime/tm/
    // for other fields in the tm struct

    // The strftime function can be used to convert the date to a null
    // terminated char array for easy printing
    char buf[80];
    strftime(buf, sizeof(buf), "%m/%d/%Y %H:%M:%S", now_as_tm_date);
    std::cout << "Current date and time: " << buf << std::endl;
    return 0;
}

Run the code below and see the comments.

Upvotes: 2

Related Questions