最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Is it possible to use std::chrono to create a datetime type which is not linked to a particular clock or implementation of

programmeradmin0浏览0评论

I'm trying to figure out how to use std::chrono to create and manipulate a datetime type.

In particular, I need some kind of type to store a datetime type. The input and output of my program will be JSON formatted data. JSON is used for data serialization when sending and receiving data from a network.

JSON does not support datetime types, however it does support strings.

The tl;dr for this is that I need some type or structure which can store a datetime type, and I need to be able to convert between that type and a std::string type.


For this question to be coherent I need to provide a bit of context.

To review the situation:

  • I am working on a Linux system. Linux supports two kinds of clocks. There is the CLOCK_REALTIME, and the CLOCK_MONOTONIC. (There are others in addition to this, but these are the interesting ones.) The clock can be accessed by calling the clock_gettime function. This talks to the OS, and returns the clock value for the chosen type of clock.
  • C++ provides std::chrono which has different kinds of clocks. I'm not sure exactly how these map to the underlying Linux clocks. I would guess that std::chrono::system_time is a CLOCK_REALTIME, and std::chrono::steady_clock is a CLOCK_MONOTONIC.
  • There are other types of clock in std::chrono. I don't know what they map to. Maybe some of them don't map to any clock_gettime function at all.
  • Since C++ and std::chrono is cross platform, it is presumably the case that other Operating Systems provide similar types of clock to those provided by Linux. I don't expect the implementation of the clocks contained within std::chrono to behave the same way on different platforms. Some platforms might only have a single type of "clock get time" function, for example.
  • For some (all?) of the clock types within std::chrono, there is a ::now() function, which returns the current time, using whichever is the relevant underlying implementation.
  • Put another way, a now() function is the std::chrono library equivalent of the lower level clock_gettime function. (Or whatever is the equivalent for other platforms. eg: Windows will have some other function, it is probably not called clock_gettime.)

Here's where my confusion starts.

  • What kind of std::chrono clock can I use if I don't need something which is attached to a particular implementation of a clock_gettime function?

To phrase this in a different way

  • Does std::chrono have a clock type which does not have a now() implementation?

To go back to the first few paragraphs in this question, I want to write some code which converts a string representation of a datetime into some C++ type.

For example

2025-02-09T15:39:00.123456789+0000 // example

I think the way to do it is to convert this string into a std::chrono::time_point.

However, a time_point is a templated class, which required some kind of class Clock to be specified.

  • See here:

It doesn't seem to make much sense to use steady_clock or system_clock here, since both of those are connected to a particular implementation of a now() function, with an underlying clock_gettime implementation.

Put another way, if I were to use one of these options, there doesn't seem to be a sensible way to choose between them.

Have I understood everything correctly here? I'm wondering if perhaps I have misunderstood something and perhaps this is the source of my confusion.

I'm trying to figure out how to use std::chrono to create and manipulate a datetime type.

In particular, I need some kind of type to store a datetime type. The input and output of my program will be JSON formatted data. JSON is used for data serialization when sending and receiving data from a network.

JSON does not support datetime types, however it does support strings.

The tl;dr for this is that I need some type or structure which can store a datetime type, and I need to be able to convert between that type and a std::string type.


For this question to be coherent I need to provide a bit of context.

To review the situation:

  • I am working on a Linux system. Linux supports two kinds of clocks. There is the CLOCK_REALTIME, and the CLOCK_MONOTONIC. (There are others in addition to this, but these are the interesting ones.) The clock can be accessed by calling the clock_gettime function. This talks to the OS, and returns the clock value for the chosen type of clock.
  • C++ provides std::chrono which has different kinds of clocks. I'm not sure exactly how these map to the underlying Linux clocks. I would guess that std::chrono::system_time is a CLOCK_REALTIME, and std::chrono::steady_clock is a CLOCK_MONOTONIC.
  • There are other types of clock in std::chrono. I don't know what they map to. Maybe some of them don't map to any clock_gettime function at all.
  • Since C++ and std::chrono is cross platform, it is presumably the case that other Operating Systems provide similar types of clock to those provided by Linux. I don't expect the implementation of the clocks contained within std::chrono to behave the same way on different platforms. Some platforms might only have a single type of "clock get time" function, for example.
  • For some (all?) of the clock types within std::chrono, there is a ::now() function, which returns the current time, using whichever is the relevant underlying implementation.
  • Put another way, a now() function is the std::chrono library equivalent of the lower level clock_gettime function. (Or whatever is the equivalent for other platforms. eg: Windows will have some other function, it is probably not called clock_gettime.)

Here's where my confusion starts.

  • What kind of std::chrono clock can I use if I don't need something which is attached to a particular implementation of a clock_gettime function?

To phrase this in a different way

  • Does std::chrono have a clock type which does not have a now() implementation?

To go back to the first few paragraphs in this question, I want to write some code which converts a string representation of a datetime into some C++ type.

For example

2025-02-09T15:39:00.123456789+0000 // example

I think the way to do it is to convert this string into a std::chrono::time_point.

However, a time_point is a templated class, which required some kind of class Clock to be specified.

  • See here: https://en.cppreference.com/w/cpp/chrono/time_point

It doesn't seem to make much sense to use steady_clock or system_clock here, since both of those are connected to a particular implementation of a now() function, with an underlying clock_gettime implementation.

Put another way, if I were to use one of these options, there doesn't seem to be a sensible way to choose between them.

Have I understood everything correctly here? I'm wondering if perhaps I have misunderstood something and perhaps this is the source of my confusion.

Share Improve this question asked yesterday user2138149user2138149 16.8k30 gold badges145 silver badges287 bronze badges 4
  • 4 I'm not sure I understand your aversion to having a time_point tied to a clock? time_point is just a number, without a clock that number is fairly meaningless. If all you want to do is convert a date time from a string representation and back again then system_clock is exactly what you want, it'll behave similarly on all platforms, that's the whole point of the standard library – Alan Birtles Commented yesterday
  • @AlanBirtles There may be no particular reason to be averse to it. I just find it a bit strange to use a type for manipulating datetime values when that type has a now function, and this is really one of the core reasons to use the type. The point of a system_clock or a steady_clock is to be able to get a value representing the current time using ::now(). To use them for some other primary purpose just feels a bit strange. – user2138149 Commented 20 hours ago
  • Have you looked at the C time capabilities, like time_t and related functions? That gives you a time point you can convert but it can be any value you like.. – Rud48 Commented 19 hours ago
  • It's no different to using time_t to store a time, that has a now function too. If you don't want to get the current time, just don't call now, it being part of the clock doesn't do you any harm – Alan Birtles Commented 12 hours ago
Add a comment  | 

1 Answer 1

Reset to default 1

There are lots of good questions here. I'll try to answer all of them:

Is it possible to use std::chrono to create a datetime type which is not linked to a particular clock or implementation of a "now" function?

Yes. For example you could create your own clock type which does nothing, and does not contain a now() function. That might look like this:

struct no_clock {};
template<class Duration>
    using clock_less_time  = time_point<no_clock, Duration>;

Now you can say: clock_less_time t{}; and t is a chrono::time_point based on no_clock. And if you try to say: decltype(t)::clock::now(), you will get a compile-time error because that statement attempts to call no_clock::now().

C++ provides std::chrono which has different kinds of clocks. I'm not sure exactly how these map to the underlying Linux clocks. I would guess that std::chrono::system_time is a CLOCK_REALTIME, and std::chrono::steady_clock is a CLOCK_MONOTONIC.

That is correct.

Does std::chrono have a clock type which does not have a now() implementation?

Yes: std::chrono::local_t. local_t is an empty struct just like the no_clock example above. There also exists a local_time templated type alias to help make time_points with that clock:

template<class Duration>
    using local_time  = time_point<local_t, Duration>;

And you could use local_time for your purposes if you wanted. That would be especially appropriate if you strings represented local time of a possibly yet to be specified time zone.

For example

2025-02-09T15:39:00.123456789+0000 // example

I think the way to do it is to convert this string into a std::chrono::time_point.

Now I'm a little confused. This string represents a point in time in UTC, or if the time zone offset were non-zero, a local time in the time zone with said non-zero offset.

There are two ways to parse this:

  1. As sys_time (time_point based on system_clock). The definition of these time points is that they represent UTC (as does CLOCK_REALTIME).

If you parse as a sys_time, and the offset is non-zero, it will subtract the offset from the parsed local time to produce the sys_time. Example code:

istringstream in{"2025-02-09T15:39:00.123456789+0000"};
sys_time<nanoseconds> tp;
in >> parse("%FT%T%z", tp);
// tp now has the value 2025-02-09 15:39:00.123456789 UTC
  1. As local_time. If you parse into local_time you get the exact value of the string without taking the offset into account. You have the option of saving the parsed value of the offset, or throwing it away. Either way, the offset does not alter the local time parsed.

The second option would look like:

istringstream in{"2025-02-09T15:39:00.123456789+0000"};
local_time<nanoseconds> tp;
in >> parse("%FT%T%z", tp);
// tp now has the value 2025-02-09 15:39:00.123456789

If you wanted to save the offset, that would look like:

istringstream in{"2025-02-09T15:39:00.123456789+0000"};
local_time<nanoseconds> tp;
minutes offset;
in >> parse("%FT%T%z", tp, offset);
// tp now has the value 2025-02-09 15:39:00.123456789
// offset has the value 0min

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论