检测夏令时算法

Detect daylight saving time algorithm

我写了一个 class Instant 管理关于时区和一些夏令时算法(EuropeUSA)的日期和时间。 到目前为止,我让 class 的用户指定 DST 算法,默认值为 Europe。但是现在我想自动检测为默认值。

这是我的第一个实现。它似乎适用于我的 Windows 7 工作站(编译器:intel 14.0)(我必须澄清列表),但它不适用于 Linux openSUSE(编译器:gcc 4.8.3),因为tz.tz_dsttime 始终为 0。

typedef enum {
    DST_ALGO_NONE   = 0,
    DST_ALGO_EUROPE = 1,
    DST_ALGO_USA    = 2
} TimeZoneType;

TimeZoneType auto_detect_dst_algorithm()
{
#   ifdef WIN32
        TIME_ZONE_INFORMATION tz;
        GetTimeZoneInformation(&tz);
        std::wstring tz_wstr = tz.DaylightName;
        std::string tz_str(tz_wstr.begin(), tz_wstr.end());
        if(   tz_str.find("Romance") != std::string::npos
           || tz_str.find("RST") != std::string::npos
           || tz_str.find("Central Europe") != std::string::npos
           || tz_str.find("CEST") != std::string::npos
           || tz_str.find("Middle Europe") != std::string::npos
           || tz_str.find("MET") != std::string::npos
           || tz_str.find("Western Europe") != std::string::npos
           || tz_str.find("WET") != std::string::npos )
        {
            return DST_ALGO_EUROPE;
        }
        else if(   tz_str.find("Pacific") != std::string::npos
                || tz_str.find("PDT") != std::string::npos )
        {
            return DST_ALGO_USA;
        }
        else
        {
            return DST_ALGO_NONE;
        }
#   else
        struct timeval tv;
        struct timezone tz;
        gettimeofday(&tv, &tz);
        if(tz.tz_dsttime == 1)
        {
            return DST_ALGO_USA;
        }
        else if(tz.tz_dsttime == 3 || tz.tz_dsttime == 4)
        {
            return DST_ALGO_EUROPE;
        }
        else
        {
            return DST_ALGO_NONE;
        }
#   endif
}

这样做的好方法是什么?

来自the gettimeofday man page

On Linux, with glibc, the setting of the tz_dsttime field of struct timezone has never been used by settimeofday() or gettimeofday(). Thus, the following is purely of historical interest.

On old systems, the field tz_dsttime contains a symbolic constant...

... Of course it turned out that the period in which Daylight Saving Time is in force cannot be given by a simple algorithm, one per country; indeed, this period is determined by unpredictable political decisions. So this method of representing timezones has been abandoned.

原题中的评论是正确的。您不应该尝试自己实现它,尤其是使用废弃的 API.

即使在您的示例代码的 Windows 部分,您也会对您可能在 DaylightName 字段中找到的内容做出很多假设。您确实意识到时区比您正在测试的时区多得多,对吗?此外,在用户选择英语以外的主要语言的系统上,这些字符串的显示结果会大不相同。

C++ 有很多不错的时区库。任何有价值的东西都将使用 the IANA tz database as its source. I'd take a good look at the best practices FAQ, and the timezone tag wiki. In particular, the FAQ recommends CCTZ, ICU, or TZ,并警告不要为此功能使用 Boost。