C ++:如何使用ICU按给定的时区偏移量获取当前时间?

时间:2019-03-17 12:15:27

标签: c++ timezone icu

我想使用ICU library通过给定的时区偏移量获取当前时间(也需要计算夏时制),我尝试了以下代码,但是snext函数返回NULL,ICU库版本是6.1,CentOS 7.6 64位+ 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;

1 个答案:

答案 0 :(得分:2)

来自the ICU documentation

  

可能存在多个具有相同GMT偏移量的区域,它们在处理夏时制方面的方式有所不同。例如,亚利桑那州不遵守夏令时。如果您要求对应于GMT-7:00的时区ID,则会返回两个时区ID的枚举:“美国/丹佛”,对应于冬季的“山区标准时间”和“冬季的夏时制”夏季,以及“ America / Phoenix”(美国/凤凰城),它全年都对应于“山区标准时间”,即使在夏季也是如此。

换句话说,如果您只需要输入偏移量,则不能正确计算夏令时。许多不同的区域可能共享此偏移量,有些可能在标准时间使用,有些可能在白天使用,而有些可能全年使用。

也了解世界各地使用DST的方式不同。有些比美国早或晚开始,有些根本不使用它。在南半球使用它的人通常在冬季,而北半球在夏天,反之亦然。一个时区只切换30分钟,而不是通常的60分钟。在全球范围内,没有DST的单一实现。

在您的代码中,您正在创建在标准时间(或全年)内使用给定偏移量的区域的枚举,但是您仅检查枚举的第一项。无法保证第一项是正确使用的项。

您能做的最好的事情就是获取当前的偏移量时间,而您实际上并不需要ICU。

相关问题