【发布时间】:2010-01-26 01:16:44
【问题描述】:
在我见过的大多数例子中:
time_zone_ptr zone( new posix_time_zone("MST-07") );
但我只想获取运行代码的机器的当前时区。我不想硬编码时区名称。
【问题讨论】:
标签: c++ boost timezone boost-date-time
在我见过的大多数例子中:
time_zone_ptr zone( new posix_time_zone("MST-07") );
但我只想获取运行代码的机器的当前时区。我不想硬编码时区名称。
【问题讨论】:
标签: c++ boost timezone boost-date-time
普通 posix:call tzset, use tzname.
#include <ctime>
tzset();
time_zone_ptr zone(new posix_time_zone(tzname[localtime(0)->tm_isdst]));
添加了glibc/bsd 的Posix:
time_zone_ptr zone(new posix_time_zone(localtime(0)->tm_zone));
以上缩写为Posix timezones,根据与 UTC 的偏移量定义,并且随着时间的推移不稳定(有更长的形式可以包括 DST 过渡,但不包括政治和历史过渡)。
ICU 是可移植的,并且具有将系统时区检索为 Olson 时区的逻辑(sumwale 的 sn-p):
// Link with LDLIBS=`pkg-config icu-i18n --libs`
#include <unicode/timezone.h>
#include <iostream>
using namespace U_ICU_NAMESPACE;
int main() {
TimeZone* tz = TimeZone::createDefault();
UnicodeString us;
std::string s;
tz->getID(us);
us.toUTF8String(s);
std::cout << "Current timezone ID: " << s << '\n';
delete tz;
}
在 Linux 上,ICU 被实现为与 tzset 兼容,并查看 TZ 和 /etc/localtime,在最近的 Linux 系统上,它们被指定为包含 Olson 标识符 (here's the history) 的符号链接。实现细节见uprv_tzname。
Boost 不知道如何使用 Olson 标识符。您可以使用非 DST 和 DST 偏移量构建posix_time_zone,但此时最好继续使用 ICU 实现。见this Boost FAQ。
【讨论】:
_get_tzname() 实现返回了一个名称,例如“太平洋标准时间”; Boost 的posix_time_zone 想要类似“PST”的东西。另外,顺便说一句,tzname(POSIX,标准称之为_tzname)是一个二维字符数组。 [MSVC 还提供 TZNAME_MAX,如果你是 #define _POSIX_,但设置为 10,显然是早期实现的疏忽。]
_tzset() 仅适用于 UTC 偏移量,但不能正确解释来自 TZ 变量的 DST 更改定义(某些特定的美国规则是硬编码的)。
今天已经很晚了,但我一直在寻找类似的东西,希望这可以帮助其他人。以下使用 strftime 的(非增强)方式似乎适用于大多数平台:
time_t ts = 0;
struct tm t;
char buf[16];
::localtime_r(&ts, &t);
::strftime(buf, sizeof(buf), "%z", &t);
std::cout << "Current timezone: " << buf << std::endl;
::strftime(buf, sizeof(buf), "%Z", &t);
std::cout << "Current timezone: " << buf << std::endl;
或者可以将 std::time_put 用于纯 C++ 版本。
【讨论】:
好吧,也许您可以使用 GeoIP 库来做到这一点。我知道这有点矫枉过正,但由于世界上大多数计算机都连接到互联网,你可能会侥幸逃脱。据我开发的那个人说,它的准确率超过 99%。
注意:这是一个愚蠢的想法。我只是在寻找答案。
【讨论】:
为了正确回答这个问题,重要的是要了解 Boost 中的时区支持受到严格限制。
它主要关注 POSIX 时区,它有几个限制。这些限制在the timezone tag wiki 的 POSIX 部分中进行了讨论,因此在此不再赘述。
它具有处理 IANA/Olson 时区 ID 的函数,但它人为地将这些映射到 POSIX 值 - 这具有将时区扁平化为历史上的单个点的效果。这些映射存储在 Boost 源代码中的a csv file 中。
csv 文件自 2011 年 4 月以来一直没有更新,从那时起对时区进行了许多更改。所以,它确实拥有的映射有些不准确。
一般来说,我不建议使用 Boost 来处理时区。相反,请考虑ICU TimeZone Classes,它是ICU 项目的一部分。您会发现它们是完全可移植的,并且它们具有完整且正确的时区支持。
值得一提的是,ICU 被用于许多流行的应用程序中。例如,Google Chrome 网络浏览器从 ICU 获得其时区支持。
在 ICU 中,当前本地系统时区可用作 默认 时区。您可以在 ICU 文档中的 "Factory Methods and the Default Timezone" 部分阅读更多内容。
【讨论】:
time_zone_ptr 正确设置为机器的当前时区的任何类型 - 这就是问题所在。您可以想象我宁愿不添加另一个依赖项,问题是关于提升,但如果唯一的可能性是使用 ICU,那就这样吧。不幸的是,您答案的这一部分,唯一直接相关的部分,是仅链接。
您总是可以尝试从 boost 中获取世界时间和当地时间并检查差异,但它可能充满了警告。
【讨论】: