我想使用ICU library来获取当前时间给定的时区偏移量(也需要计算夏令时),我试过下面的代码,但是snext函数返回NULL,ICU库版本是6.1,CentOS 7.6 64 bit + gcc 6.4.1。
timezoneOffset = 1; //(UTC + 1)
UErrorCode success = U_ZERO_ERROR;
U_ICU_NAMESPACE::UnicodeString dateReturned, curTZNameEn, curTZNameFr;
int32_t stdOffset = 0;
int32_t dstOffset = 0;
//
// Create a Calendar to get current date
U_ICU_NAMESPACE::Calendar* calendar = U_ICU_NAMESPACE::Calendar::createInstance(success);
if (!calendar)
{
return;
}
success = U_ZERO_ERROR;
UErrorCode ec;
std::string errorName;
int32_t rawOffset = timezoneOffset * 3600 * 1000;
U_ICU_NAMESPACE::StringEnumeration* se = U_ICU_NAMESPACE::TimeZone::createEnumeration(rawOffset); // Obtain timezones by GMT timezone offset
if (se)
{
auto next = se->snext(ec);
if (next && ec == U_ZERO_ERROR)
{
U_ICU_NAMESPACE::TimeZone *tzWest = U_ICU_NAMESPACE::TimeZone::createTimeZone(*next);
if (tzWest)
{
UDate curDate = calendar->getNow();
tzWest->getOffset(curDate, false, stdOffset, dstOffset, success);
if (U_SUCCESS(success))
{
timezoneOffset = (stdOffset / (1000 * 60 * 60) + dstOffset / (1000 * 60 * 60));
}
}
}
else
{
errorName = u_errorName(ec); // The error name is "bogus error"
}
delete se;
}
delete calendar;
可能存在多个具有相同GMT偏移的区域,这些区域处理夏令时的方式不同。例如,亚利桑那州没有观察夏令时。如果您要求对应于GMT-7:00的时区ID,您将获得两个时区ID的枚举:“America / Denver”,对应于冬季的山地标准时间和山区的夏令时时间夏天,和“美国/凤凰”,即使在夏天,也全年对应山地标准时间。
换句话说,如果您输入的所有内容都是偏移量,则无法正确计算夏令时。许多不同的区域可能共享此偏移,有些可能在标准时间使用它,有些可能在白天使用它,有些可能全年使用它。
还要了解世界不同地区使用DST的方式不同。有些人比美国早或晚开始,有些人根本不使用它。那些在南半球使用它的人通常在冬季,而北半球在夏季时,反之亦然。一个时区仅切换30分钟而不是通常的60分钟。全球范围内没有单一的DST实施。
在您的代码中,您将创建在标准时间(或全年)内使用给定偏移的区域枚举,但您只检查枚举的第一项。无法保证第一项是正确使用的项目。
你能做的最好的事情就是获得你所拥有的偏移的当前时间,而你真的不需要ICU来做到这一点。