我对此做了一些研究,我有非常有说服力的证据,答案是肯定的,答案是否定的.我不确定相信哪一方.
首先,我在cppreference.com上找到的文档和 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf似乎对此没有任何说明.我认为这是语言环境不支持时区的证据.
但https://en.cppreference.com/w/cpp/locale/time_get/get和https://en.cppreference.com/w/cpp/locale/time_put/put 都说:
%z以ISO 8601格式(例如-0430)写入UTC的偏移量,或者如果时区信息不可用则不写入字符%%Z写入时区名称或缩写,如果时区信息不可用则不写入字符(区域设置)依赖)
这似乎表明存在与locale()对象关联的时区SOMETIMES.
现在,如果您使用语言环境en_US.utf8(我最喜欢的一个;-)),那么确实没有任何明智的时区可以关联(美国至少包含4个或更多时区).
所以有时间去实证.
我跑了代码:
#include <iostream>
#include <cstdlib>
#include <locale>
#include <sstream>
using namespace std;
int main ()
{
// locale l;
locale l = locale::classic ();
tm when{};
const time_put<char>& tmput = use_facet<time_put<char>> (l);
ostringstream oss;
oss.imbue (l);
static const string kTZOffsetPattern_{"%z"};
tmput.put (oss, oss, ' ', &when, kTZOffsetPattern_.c_str (), kTZOffsetPattern_.c_str () + kTZOffsetPattern_.length ());
cout << oss.str ();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在Linux(ubuntu)上,这给出了我期望的答案,+ 0000(好吧,我也不会对错误或空字符串感到惊讶).
但是在Windows(visual studio.net 2k17 - 15.8.7)上 - 这给出了:-0500
是的,正如你可能已经猜到的那样,我正在东部时区进行测试.但我仍然期望0,或空字符串(特别是对于locale :: classic()情况).
How*_*ant 10
直接回答你的问题
C++语言环境是否具有关联的时区?
没有.
它将来也不会.正如在问题中正确指出的那样,对于许多语言环境而言,由于语言环境所代表的地理区域可以具有多个时区,因此没有意义.
C标准确实在规范中说strftime:
%Z由区域设置的时区名称或缩写替换,如果没有时区可确定,则替换为无字符.[tm_isdst]
但是C规范struct lconv没有提供这样的成员来存储该信息.规范确实允许实现添加此类成员,但实际上,实现不会使用C语言环境存储该信息.
C++语言环境根据C规范,POSIX规范以及一些添加来定义time_put和time_get定义自己,这些添加不包括时区名称或缩写.strftimestrptime
POSIX规范strftime比C规范更详细,并删除与"locale"的关联:
Z如果不存在时区信息,则替换为时区名称或缩写,或者不替换为字节.[ tm_isdst]
POSIX规范struct lconv也比C规范更详细,但仍然没有为时区名称或缩写提供存储.
但是未来确实带来了更容易和有效地访问时区信息的希望,至少在C++中如此.
在C++ 20之前,C++具有以下知识:
单一时间标准:UTC,由Unix时间密切建模.
单个时区:由计算机的用户或管理员设置的"本地时区".UTC也可以用作本地时区.
如上所述,本地时区不是 C++(或C)语言环境数据的一部分.语言环境数据确实包含一些日历数据,例如:
UTC offset(%z)和时区缩写(%Z)可能是可用的,但会作为本地时区数据的一部分而不是当前的区域设置数据存储,主要是因为之间没有良好的一对一映射时区和区域设置.
解释OP问题中提供的代码所发生的事情
在您的示例中:将 tm when{};所有成员归零tm,包括tm_isdst.当tm_isdst为零时,这意味着对于此特定,已知夏令时不起作用tm.
tm也允许有标准未指定的成员.一个流行的扩展是拥有一个tm_gmtoff以秒为单位保持UTC偏移的成员.如果您的Linux实现具有这样的成员,tm when{};则将其设置为0秒.如果您的Windows实现并没有这样的成员,UTC的本地时区的偏移将存储在别处.这解释了您所看到的差异,并且两种实现都是一致的.
有关如何访问时区的有用信息,因为C++语言环境不提供访问权限
在草案C++ 20规范中,存在一个名为的新类型std::chrono::time_zone.其中一个成员函数time_zone是:
template<class Duration> sys_info get_info(const sys_time<Duration>& st) const;
Run Code Online (Sandbox Code Playgroud)
sys_time<Duration>只是一个system_clock::time_point,但任何精度.所以,你给time_zone一个time_point,你得到一个sys_info包含各种有关的有用信息是 time_zone在那个 time_point:
struct sys_info
{
sys_seconds begin;
sys_seconds end;
seconds offset;
minutes save;
string abbrev;
};
Run Code Online (Sandbox Code Playgroud)
[begin, end)告诉您此信息的有效时间(这些是UTC时间点).offset是time_zone当前的UTC偏移量seconds.save != 0min,time_zone目前被认为是夏令时.time_zone目前的缩写存储在abbrev.此外,还有一个非会员功能:
const time_zone* current_zone();
Run Code Online (Sandbox Code Playgroud)
它返回指向当前本地时区的指针.总而言之,这是一个C++ 20程序,它打印出有关当前本地时区的有趣信息:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
std::cout << current_zone()->get_info(system_clock::now()) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
这只是输出给我:
2018-03-11 07:00:00
2018-11-04 06:00:00
-04:00:00
01:00
EDT
Run Code Online (Sandbox Code Playgroud)
如果您愿意,可以使用Howard Hinnant的时区库,使用C++ 11,14或17来试验C++ 20的这一部分.该库将所有内容放在命名空间中date而不是std::chrono.
您还可以获取有关任何 IANA时区的信息,例如:
#include "date/tz.h"
#include <chrono>
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << locate_zone("Australia/Sydney")->get_info(system_clock::now()) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
只为我输出:
2018-10-06 16:00:00
2019-04-06 16:00:00
11:00:00
01:00
AEDT
Run Code Online (Sandbox Code Playgroud)
请注意,即使在C++ 20中,时区和语言环境也没有耦合.这样做是没有意义的.
| 归档时间: |
|
| 查看次数: |
1078 次 |
| 最近记录: |