admin管理员组文章数量:1122832
I want to convert a UTC year, month, day to a std::chrono::time_point
(and also display it).
#include <chrono>
using namespace std::chrono;
void DisplayDate(int y, int m, int d) {//e.g. 2024, 11, 22
time_point<system_clock> tp;
//tp = system_clock::now(); // this works as expected.
tp = system_clock::time_point(years(y-1970) + months(m-1) + days(d-1));// this doesn't
std::wstring s = std::format(L"{:%Y-%m-%d %H:%M:%S}", zoned_time{current_zone(), tp});
wprintf(s.c_str());
}
Here DisplayDate(2024,11,22)
yields 2024-11-21 04:07:48.0000000
, but I would expect 2024-11-22 00:00:00.0000000
and I am at a loss (especially) where the 04:07:48
comes from and how to fix it. Especially the strange offset of 7:48
puzzles me, even after hours of looking into this.
I could use the std::tm
detour from How to get chrono time_point from year, month, day, hour, minute, second, millisecond? but I want to understand how to do this directly.
I want to convert a UTC year, month, day to a std::chrono::time_point
(and also display it).
#include <chrono>
using namespace std::chrono;
void DisplayDate(int y, int m, int d) {//e.g. 2024, 11, 22
time_point<system_clock> tp;
//tp = system_clock::now(); // this works as expected.
tp = system_clock::time_point(years(y-1970) + months(m-1) + days(d-1));// this doesn't
std::wstring s = std::format(L"{:%Y-%m-%d %H:%M:%S}", zoned_time{current_zone(), tp});
wprintf(s.c_str());
}
Here DisplayDate(2024,11,22)
yields 2024-11-21 04:07:48.0000000
, but I would expect 2024-11-22 00:00:00.0000000
and I am at a loss (especially) where the 04:07:48
comes from and how to fix it. Especially the strange offset of 7:48
puzzles me, even after hours of looking into this.
I could use the std::tm
detour from How to get chrono time_point from year, month, day, hour, minute, second, millisecond? but I want to understand how to do this directly.
1 Answer
Reset to default 5time_point<system_clock> tp;
The above is correct and fine. But just fyi, here is another way to say the same thing:
system_clock::time_point tp;
Which you choose is just a matter of style and readability for you.
tp = system_clock::time_point(years(y-1970) + months(m-1) + days(d-1));
This doesn't do what you think it does.
years
(note plural) is a duration
with the length of the average civil year: 365.2425 days.
months
(note plural) is a duration
with the length of the average civil month: 30.436875 days. This is exactly 1/12 of years
.
What you intend is to convert the {y, m, d}
triple to a year_month_day
data structure, and then convert that to a days-precision time_point
based on system_clock
, which will subsequently implicitly convert to a system_clock::time_point
. Sounds complicated. It is not:
tp = sys_days{year{y}/m/d};
The subexpression year{y}
creates a type std::chrono::year
from y
. The offset is year 0. So 2024 means year 2024.
The subexpression year{y}/m/d
creates a type year_month_day
which does no computation but merely stores y
, m
, and d
. For each of the fields the offset is 0. 11
for month means November
. 22
for day means the day 22 in the indicated month.
A more verbose but equivalent statement would be: year{m}/month{m}/day{d}
. The 2 latter types are implied by specifying the first type year
. Note that all of these type names are singular, not plural. These singular types are "calendrical specifiers". Plural types are duration
s.
sys_days
is just a type alias for a time_point
based on system_clock
with a precision of days
. And there is an implicit conversion from year_month_day
to sys_days
. Here I'm using explicit conversion syntax just because it is convenient to do so.
std::wstring s = std::format(L"{:%Y-%m-%d %H:%M:%S}\n", zoned_time{current_zone(), tp});
time_point
s based on system_clock
are UTC. If what you want is UTC, there is no need to involve any time_zone
, including your computer's currently set time_zone
returned by current_zone()
. You can just format
tp
directly:
std::wstring s = std::format(L"{:%Y-%m-%d %H:%M:%S}\n", tp);
Furthermore, there exists "shortcuts" for both %Y-%m-%d
and %H:%M:%S
if you prefer. They are %F
and %T
respectively. They offer no advantages or disadvantages besides what you may perceive as readability (either less or more, your choice). But the above line could be rewritten as:
std::wstring s = std::format(L"{:%F %T}\n", tp);
In either case the subsequent wprintf
will output:
2024-11-22 00:00:00.0000000
Involving zoned_time
and current_zone
in the format
statement causes the format
to convert the sys_time
(UTC) to local_time
according to your computer's locally set time_zone
obtained via current_zone()
.
From the comments:
What would be the format if I wanted millisecond precision, like for example 00:00:00.123.
The easiest way to control the precision for formatting is to control the precision for your entire use case. That is, traffic in millisecond precision from the point of creation of your time_point
s, not just at format-time.
In this example that looks like:
sys_time<milliseconds> tp = sys_days{year{y}/m/d};
And the output is now:
2024-11-22 00:00:00.000
sys_time
is just a template type alias for time_point<system_clock, D>
where D
is whatever precision you want. %T
will print out the full precision of whatever it is given.
Another way to achieve the same thing is:
auto tp = sys_days{year{y}/m/d} + 0ms;
Now the type of tp
is deduced as sys_time<milliseconds>
from the precision of the initialization expression.
The same technique is used to specify a time of day (UTC):
#include <chrono>
#include <format>
#include <iostream>
void
DisplayDateTime(int y, int m, int d, int h, int M, int s, int ms)
{
using namespace std::chrono;
auto tp = sys_days{year{y}/m/d} + hours{h} + minutes{M} + seconds{s}
+ milliseconds{ms};
std::wstring str = std::format(L"{:%F %T}\n", tp);
wprintf(str.c_str());
}
int
main()
{
DisplayDateTime(2024, 11, 22, 16, 19, 13, 127);
}
Output:
2024-11-22 16:19:13.127
本文标签: cHow to set a systemclock timepoint with yearmonthdayStack Overflow
版权声明:本文标题:c++ - How to set a system_clock time_point with year, month, day - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736300087a1930693.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论