显示针对不同时区格式化的 ICU UDate

Display ICU UDate formatted for different timezones

在下面的例子中,我想在不同的时区格式化EPOCH (1/1/1970)。例如,我可能希望使用洛杉矶时区格式化EPOCH and/or使用纽约时区格式化EPOCH。

UErrorCode uErrorCode = U_ZERO_ERROR;
UnicodeString unicodeString;
UDate uDate;

icu::Locale locale = icu::Locale("en");
TimeZone* timeZone = TimeZone::createTimeZone("America/Los_Angeles");
Calendar* calendar = Calendar::createInstance(timeZone, uErrorCode);

// setting calendar to EPOCH, e.g. zero MS from 1/1/1970
calendar->setTime(0, uErrorCode);

// get calendar time as milliseconds (UDate)
uDate = calendar->getTime(uErrorCode);

DateFormat* dateFormat = DateFormat::createDateTimeInstance(
    icu::DateFormat::MEDIUM,    // date style
    icu::DateFormat::SHORT,     // time style
    locale);

unicodeString = dateFormat->format(uDate, unicodeString, uErrorCode);

std::string str;
unicodeString.toUTF8String(str);
std::cout << "Date: " << str;

// Use getOffset to get the stdOffset and dstOffset for the given time
int32_t stdOffset, dstOffset;
timeZone->getOffset(uDate, true, stdOffset, dstOffset, uErrorCode);
std::cout << " | ";
std::cout << "Time zone STD offset: " << stdOffset / (1000 * 60 * 60) << " | ";
std::cout << "Time zone DST offset: " << dstOffset / (1000 * 60 * 60) << std::endl;

我遇到的问题是输出的格式不符合时区。

这是使用 洛杉矶 时区时的输出:

日期:1969 年 12 月 31 日,6:00 下午 |时区标准偏差:-8 |时区 DST 偏移量:0

这是使用 纽约 时区时的输出:

日期:1969 年 12 月 31 日,6:00 下午 |时区标准偏差:-5 |时区 DST 偏移量:0

请注意日期不是 EPOCH,其次请注意两个输出的日期和时间是相同的。 偏移量是正确的,但date/time显示不正确

更新

重要的是要注意显示的 date/time 比我现在晚了 6 小时(-6 UTC),这意味着你添加 6 小时12 月。 1969 年 31 日 6:00PM 等于 EPOCH 1970 年 1 月 1 日 12:00AM.

ICU 正在自动使用我的 PC 的时区,因为我发现在使用 DateFormat::Format(...) 格式化 date/time 时无法指定时区。如果 format() 接受一个时区参数来覆盖我电脑的本地时区,我就不会遇到这个问题。

您应该调用 dateFormat->setTimeZone(*timeZone) 来指定时区。

@earts 做对了,因为您是根据标量时间值而不是日历进行格式化的。

或者,您可以格式化 Calendar 对象本身,它将使用该日历中的时区和时间:

unicodeString = dateFormat -> format(*calendar,
                                     unicodeString,
                                     (FieldPositionIterator*) nullptr, // ignored
                                     uErrorCode);

注意,使用上述函数时,日历类型最好与日期格式匹配。一个简单的方法是确保在创建日历时传入 locale 参数:

// above:
Calendar* calendar = Calendar::createInstance(timeZone, locale, uErrorCode);