C :如何使用ICU通过给定的时区偏移来获得当前时间

C++: How could I use the ICU to get the current time by given timezone offset?

本文关键字:时间 时区 何使用 ICU      更新时间:2023-10-16

我想使用ICU库通过给定的时区偏移获得当前时间(也需要计算节省日光),我尝试了以下代码,但是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;

来自ICU文档:

可能有几次区域的GMT偏移量在处理日光节省时间的方式上有所不同。例如,亚利桑那州没有观察到日光节省时间。如果您要求与GMT-7:00相对应的时区ID,您将在两个时区ID上获得枚举夏季和"美国/凤凰",即使在夏天,也对应于山区标准时间。

换句话说,如果您拥有的所有输入只是一个偏移,则您无法正确计算日光保存时间。许多不同的区域可能会共享此偏移,有些区域可能会在标准时间使用它,有些则可能在白天使用它,有些人可能会全年使用它。

还了解,世界各地使用DST的使用方式不同。有些比美国早或晚些时候,有些根本不使用它。那些在南半球使用的人通常在冬季,而北半球则在夏季,反之亦然。一个时区仅切换30分钟而不是通常的60。

在您的代码中,您正在创建一个在标准时间(或全年)期间使用给定偏移的区域的枚举,但是您只检查枚举的第一项。没有保证第一个项目是正确使用的项目。

最好是要获得当前的偏移时间,而您实际上并不需要ICU来做到这一点。