C++ RFC3339 timestamp with milliseconds using std::chrono
Asked Answered
A

1

6

I'm creating an RFC3339 timestamp, including milliseconds and in UTC, in C++ using std::chrono like so:

#include <chrono>
#include <ctime>
#include <iomanip>

using namespace std;
using namespace std::chrono;

string now_rfc3339() {
  const auto now = system_clock::now();
  const auto millis = duration_cast<milliseconds>(now.time_since_epoch()).count() % 1000;
  const auto c_now = system_clock::to_time_t(now);

  stringstream ss;
  ss << put_time(gmtime(&c_now), "%FT%T") <<
    '.' << setfill('0') << setw(3) << millis << 'Z';
  return ss.str();
}

// output like 2019-01-23T10:18:32.079Z

(forgive the usings)

Is there a more straight forward way of getting the milliseconds of now? It seems somewhat cumbersome to %1000 the now in milliseconds to get there. Or any other comments on how to do this more idiomatic?

Atropos answered 23/1, 2019 at 10:30 Comment(0)
P
2

You could also do this with subtraction:

string
now_rfc3339()
{
    const auto now_ms = time_point_cast<milliseconds>(system_clock::now());
    const auto now_s = time_point_cast<seconds>(now_ms);
    const auto millis = now_ms - now_s;
    const auto c_now = system_clock::to_time_t(now_s);

    stringstream ss;
    ss << put_time(gmtime(&c_now), "%FT%T")
       << '.' << setfill('0') << setw(3) << millis.count() << 'Z';
    return ss.str();
}

This avoids the "magic number" 1000.

Also, there is Howard Hinnant's free, open source, single-header, header-only datetime library:

string
now_rfc3339()
{
    return date::format("%FT%TZ", time_point_cast<milliseconds>(system_clock::now()));
}

This does the same thing but with easier syntax.

Paolapaolina answered 23/1, 2019 at 14:36 Comment(1)
Thanks Howard, stumbled across your date lib already, it looks very helpful! I'll keep it in mind for the future. But in this project, there's only one place where I need that format, so I rather not include an external source for that.Atropos

© 2022 - 2025 — McMap. All rights reserved.