尽管标准未指定,但每次实施std::chrono::system_clock::now()
正在追踪Unix时间 https://en.wikipedia.org/wiki/Unix_time,它非常接近 UTC。
如果你想翻译std::chrono::system_clock::now()
到当地时间,你可以翻译system_clock::time_point
to time_t
via system_clock::to_time_t
,然后通过 C API 进行操作(例如localtime
),或者您可以尝试这个现代时区库,它构建在<chrono>
:
https://howardhinnant.github.io/date/tz.html https://howardhinnant.github.io/date/tz.html
您可以使用它来获取当前本地时间,如下所示:
#include "tz.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
auto t = make_zoned(current_zone(), system_clock::now());
std::cout << t << '\n';
}
make_zoned
是一个返回类型的工厂函数zoned_time
无论你的精度如何system_clock
支持(例如纳秒)。这是一对time_zone
and a system_clock::time_point
.
你可以获得一个local_time<Duration>
这是一个std::chrono::time_point
像这样:
auto t = make_zoned(current_zone(), system_clock::now());
auto lt = t.get_local_time();
std::cout << lt.time_since_epoch().count() << '\n';
虽然该库有一个远程API来下载IANA 时区数据库 http://www.iana.org/time-zones自动地,可以通过编译来禁用该 API-DHAS_REMOTE_API=0
。这一切都在安装说明 https://howardhinnant.github.io/date/tz.html#Installation。禁用远程 API 后,您必须从以下位置手动下载数据库:IANA 时区数据库 http://www.iana.org/time-zones(这只是一个tar.gz
).
如果您需要当前的 UTC 偏移量,可以这样获取:
auto t = make_zoned(current_zone(), system_clock::now());
auto offset = t.get_info().offset;
std::cout << offset << '\n';
在上面的代码片段中,我利用"chrono_io.h"
在同一个 github 存储库中找到并打印offset
. offset
有类型std::chrono::seconds
。这只是我的输出:
-14400s
(-0400)
最后,如果您想查找当前时区的 IANA 名称,只需:
std::cout << current_zone()->name() << '\n';
对我来说只是输出:
America/New_York
返回的类型来自name()
is std::string
。如果需要,可以记录该字符串,然后使用time_zone
使用该名称,即使这不是计算机的当前时区:
auto tz_name = current_zone()->name();
// ...
auto t = make_zoned(tz_name, system_clock::now()); // current local time in tz_name
4年后更新
该库现已成为 C++20 的一部分,并进行了以下修改:
- 的内容
"tz.h"
are in <chrono>
.
- 名称的内容在
namespace date
are in namespace std::chrono
.
-
make_zoned
不是 C++20 的一部分,因为CTAD https://en.cppreference.com/w/cpp/language/class_template_argument_deduction使它变得不必要。您可以使用zoned_time
替换它的位置并推导模板参数。
此外,自定义(用户编写的)time_zone
现在可以与https://howardhinnant.github.io/date/tz.html https://howardhinnant.github.io/date/tz.html或者使用新的 C++20<chrono>
。一个很好的定制例子time_zone
已写至此处为 POSIX 时区模型 https://github.com/HowardHinnant/date/blob/master/include/date/ptz.h。这可以用来更准确地回答原来的问题:
#include "date/ptz.h"
#include <cstdlib>
#include <iostream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
const char* tz = getenv("TZ");
if (tz == nullptr)
tz = "UTC0";
zoned_time now{Posix::time_zone{tz}, system_clock::now()};
cout << format("%F %T%z", now) << '\n';
}
With my TZ
环境变量设置为UTC+3
这只是我的输出:
2020-09-17 10:28:06.343050-0300
Notes:
-
尽管依赖于tz.h
, ptz.h
是一个仅包含头文件的库。无需安装IANA tz数据库,也无需编译tz.cpp
.
-
POSIX 指定 https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03UTC 偏移量的符号与其他所有内容(包括 POSIX 的其他部分)使用的符号相反。正偏移量是west本初子午线而不是east。这反映在本例中将 UTC 偏移量格式化为负数的输出中,这与POSIX strftime spec https://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html.
-
如果使用 C++11 或 C++14 编译它,则没有CTAD https://en.cppreference.com/w/cpp/language/class_template_argument_deduction在你的工具箱里。在这种情况下:
`
zoned_time now{Posix::time_zone{tz}, system_clock::now()};
becomes:
zoned_time<system_clock::duration, Posix::time_zone> now{Posix::time_zone{tz}, system_clock::now()};