检测夏令时算法
Detect daylight saving time algorithm
我写了一个 class Instant
管理关于时区和一些夏令时算法(Europe
和 USA
)的日期和时间。
到目前为止,我让 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
}
这样做的好方法是什么?
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。
我写了一个 class Instant
管理关于时区和一些夏令时算法(Europe
和 USA
)的日期和时间。
到目前为止,我让 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
}
这样做的好方法是什么?
On Linux, with glibc, the setting of the
tz_dsttime
field of struct timezone has never been used bysettimeofday()
orgettimeofday()
. 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。