gpt4 book ai didi

c++ - struct tm 是否将时区信息存储为其数据成员

转载 作者:行者123 更新时间:2023-12-02 12:43:50 26 4
gpt4 key购买 nike

考虑以下 C++ 代码

#include <ctime>
#include <iostream>

int main()
{
std::time_t now = std::time(nullptr);
struct tm local = *std::localtime(&now);
struct tm gm = *std::gmtime(&now);
char str[20];
std::strftime(str, 20, "%Z", &local);
std::cout << str << std::endl; // HKT
std::strftime(str, 20, "%Z", &gm);
std::cout << str << std::endl; // UTC

return 0;
}

所以存储在 now是一个明确的整数值,而 localgmstruct tm存储人类可读的日期/时间信息。然后我仅根据 struct tm 打印出格式化信息(时区)对象。

据cplusplusreferencestruct tm 的数据成员是

tm_sec  
tm_min
tm_hour
tm_mday
tm_mon
tm_year
tm_wday
tm_yday
tm_isdst

如果这就是 struct tm包含,程序如何知道其中的时区信息?也就是说,它怎么知道时区是 HKT对于 local ,时区是 UTC对于 gm

如果这还不是全部 struct tm包含,请解释它如何存储时区信息。

顺便说一句,虽然演示代码是用 C++ 编写的,但我想这个问题本质上也是一个合法的 C 问题。

最佳答案

C 标准在 7.27.1 时间的组成部分中说:

The tm structure shall contain at least the following members, in any order. The semantics of the members and their normal ranges are expressed in the comments.318)

int tm_sec;    // seconds after the minute — [0, 60]
int tm_min; // minutes after the hour — [0, 59]
int tm_hour; // hours since midnight — [0, 23]
int tm_mday; // day of the month — [1, 31]
int tm_mon; // months since January — [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday — [0, 6]
int tm_yday; // days since January 1 — [0, 365]
int tm_isdst; // Daylight Saving Time flag

(强调的是我的)

也就是说,允许实现向tm添加额外的成员。 ,正如您在 glibc/time/bits/types/struct_tm.h 中发现的那样。 POSIX 规范的措辞几乎相同。

结果是%Z (甚至 %z )在 strftime 中不能被认为是可移植的。 %Z 的规范反射(reflect)了这一点:

%Z is replaced by the locale’s time zone name or abbreviation, or by no characters if no time zone is determinable. [tm_isdst]

也就是说,供应商可以举手并简单地说:“没有可确定的时区,所以我根本不输出任何字符。”

我的观点:C 计时 API 很困惑。

<小时/>

我正在尝试为 <chrono> 中即将推出的 C++20 标准进行改进。图书馆。

C++20 规范将其从“无字符”更改为如果 time_zone 则抛出异常。缩写不可用:

http://eel.is/c++draft/time.format#3

Unless explicitly requested, the result of formatting a chrono type does not contain time zone abbreviation and time zone offset information. If the information is available, the conversion specifiers %Z and %z will format this information (respectively). [ Note: If the information is not available and a %Z or %z conversion specifier appears in the chrono-format-spec, an exception of type format_­error is thrown, as described above. — end note ]

只不过上面这段并不是描述C的strftime ,但是一个新的format运行于 std::chrono 的函数类型,而不是 tm 。另外还有一个新类型:std::chrono::zoned_time ( http://eel.is/c++draft/time.zone.zonedtime ) 总是 time_zone可用缩写(和偏移量),并且可以使用上述 format 进行格式化功能。

示例代码:

#include <chrono>
#include <iostream>

int
main()
{
using namespace std;
using namespace std::chrono;
auto now = system_clock::now();
std::cout << format("%Z\n", zoned_time{current_zone(), now}); // HKT (or whatever)
std::cout << format("%Z\n", zoned_time{"Asia/Hong_Kong", now}); // HKT or HKST
std::cout << format("%Z\n", zoned_time{"Etc/UTC", now}); // UTC
std::cout << format("%Z\n", now); // UTC
}

(免责声明:format 函数中格式化字符串的最终语法可能略有不同,但功能仍然存在。)

如果您想试用该库的预览版,它是免费且开源的:https://github.com/HowardHinnant/date

需要一些安装:https://howardhinnant.github.io/date/tz.html#Installation

在此预览中,您将需要使用 header "date/tz.h" ,库的内容在 namespace date 中而不是namespace std::chrono .

预览库可与 C++11 或更高版本一起使用。

zoned_time模板化于 std::chrono::duration它指定时间点的精度,并在上面的示例代码中使用 C++17's CTAD feature 推导出来。 。如果您在 C++11 或 C++14 中使用此预览库,语法将类似于:

cout << format("%Z\n", zoned_time<system_clock::duration>{current_zone(), now});

或者有一个非建议标准化的辅助工厂函数可以为您进行扣除:

cout << format("%Z\n", make_zoned(current_zone(), now));

(#CTAD_eliminates_factory_functions)

关于c++ - struct tm 是否将时区信息存储为其数据成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58443953/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com