Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert 32 bit unix timestamp to std::string using std::chrono

I am trying to use std::chrono to make a std::string but running into issues.

Here is the C(-ish) code I want to mimick:

std::uint32_t time_date_stamp = 1484693089;
char date[100];
struct tm *t = gmtime(reinterpret_cast<const time_t*>(&time_date_stamp));
strftime(date, sizeof(date), "%Y-%m-%d %I:%M:%S %p", t);

My starting point is always this std::uint32_t, it is from a data format I do not control.

Sorry I do not have any C++ as a starting point, I do not even know how to make a std::chrono::time_point correctly.

like image 239
Ziggy Avatar asked Jan 17 '17 22:01

Ziggy


2 Answers

<chrono> is not a library for formatting datetimes into strings. It is useful for converting different time representations (milliseconds to days, etc), adding timestamps together and such.

The only datetime formatting functions in the standard library are the ones inherited from the C standard library, including the std::strftime which you already used in the "C(-ish)" version. EDIT: As pointed out by jaggedSpire, C++11 introduced std::put_time. It provides a convenient way to stream formatted dates with the same API as used by the C functions.

Since std::gmtime (and std::localtime if you were to use that) take their argument as a unix timestamp, you don't need <chrono> to convert the time. It is already in the correct representation. Only the underlying type must be converted from std::uint32_t to std::time_t. That is not implemented portably in your C version.

A portable way to convert the timestamp, with std::put_time based formatting:

std::uint32_t time_date_stamp = 1484693089;
std::time_t temp = time_date_stamp;
std::tm* t = std::gmtime(&temp);
std::stringstream ss; // or if you're going to print, just input directly into the output stream
ss << std::put_time(t, "%Y-%m-%d %I:%M:%S %p");
std::string output = ss.str();
like image 39
eerorika Avatar answered Oct 11 '22 02:10

eerorika


Here's an easy way to do it without dropping down to C's tm using this portable C++11/14 free, open-source, header-only library.

#include "date.h"
#include <iostream>
#include <string>

int
main()
{
    std::uint32_t time_date_stamp = 1484693089;
    date::sys_seconds tp{std::chrono::seconds{time_date_stamp}};
    std::string s = date::format("%Y-%m-%d %I:%M:%S %p", tp);
    std::cout << s << '\n';
}

This outputs:

2017-01-17 10:44:49 PM

This does not have the thread-safety issues associated with the ancient gmtime C function.

date::sys_seconds above is a typedef for std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>.

like image 159
Howard Hinnant Avatar answered Oct 11 '22 04:10

Howard Hinnant