以线程安全的方式转换 C/C++ 中时区名称字符串的时区偏移量

Converting timezone offset from timezone name string in C/C++ in a thread-safe way

本文关键字:时区 偏移量 C++ 字符串 安全 线程 方式 转换      更新时间:2023-10-16

我正在尝试实现一个函数,以便可以转换给定的时区名称字符串,它确实如此:

  1. 接受输入时区字符串,例如"澳大利亚/墨尔本";
  2. 检查主机操作系统(假设它是 POSIX 环境(时区数据库;
  3. 返回时区偏移量的整数(对于 DST 中的墨尔本,为 36000(。

这可以通过调用putenv("TZ=Australia/Melbourne")来完成,但这可能不是线程安全的。

有没有办法在不putenv()的情况下做到这一点,或者以某种方式让它成为线程安全的?提前感谢!

由于编译器还不支持 C++20std::chrono库的所有功能,我将编写一个使用 Howard Hinnantdatehttps://github.com/HowardHinnant/date 库的解决方案。C++20 介绍了可用于实现所需目标的std::chrono::zoned_time

#include "date/tz.h"
#include <iostream>
int main()
{
auto current_time = std::chrono::system_clock::now();
auto la = date::zoned_time{"America/Los_Angeles", current_time};
auto sy = date::zoned_time{"Australia/Sydney", current_time};
std::cout << date::format("%Tn", sy.get_local_time() - la.get_local_time());
}

上面的示例将为您提供两个时区之间的差异。此外,如果您想获取当前操作系统的时区,您可以使用我希望将来编译器会支持的东西 -std::chrono::time_zone::name

在 C++20 中,您将能够使用std::chrono::tzdb::locate_zone(),它将给定的时区名称转换为可以查询以获取偏移量的std::chrono::time_zone对象。

没有处理时区的标准 C 函数。有符合 POSIX.1 的函数,但它们确实不是线程安全的。但是,根据您的操作系统,您可能能够打开时区数据库文件并手动分析它们。例如,在 Linux 上,您可以打开/usr/share/zoneinfo/Australia/Melbourne并根据它在 tzfile(5( 手册页中的规范对其进行解析。

除了OP的线程问题之外,另一个考虑因素:

"时区与时区名称字符串的偏移量"通常是不够的,因为偏移量因全年的数据/时间而异。

即使所选区域中没有发生年度日光调整,偏移量也可能因区域的历史而异。

long offset(tz_name)是不够的,还需要long offset(tz_name, time_t t)