|
21 | 21 | #include <folly/container/F14Map.h>
|
22 | 22 | #include <folly/container/F14Set.h>
|
23 | 23 |
|
24 |
| -#include <unicode/locid.h> |
25 |
| -#include <unicode/timezone.h> |
26 |
| -#include <unicode/unistr.h> |
27 |
| - |
28 |
| -// The ICU libraries define TRUE/FALSE macros which frequently conflict with |
29 |
| -// other libraries that use these as enum/variable names. |
30 |
| -#undef TRUE |
31 |
| -#undef FALSE |
32 |
| - |
33 | 24 | #include "velox/common/base/Exceptions.h"
|
34 | 25 | #include "velox/common/testutil/TestValue.h"
|
35 | 26 | #include "velox/external/date/tz.h"
|
| 27 | +#include "velox/type/tz/TimeZoneNames.h" |
36 | 28 |
|
37 | 29 | using facebook::velox::common::testutil::TestValue;
|
38 | 30 |
|
@@ -311,6 +303,43 @@ TDuration toLocalImpl(
|
311 | 303 | }
|
312 | 304 | return date::zoned_time{tz, timePoint}.get_local_time().time_since_epoch();
|
313 | 305 | }
|
| 306 | + |
| 307 | +template <bool isLongName> |
| 308 | +std::string getName( |
| 309 | + TimeZone::milliseconds timestamp, |
| 310 | + TimeZone::TChoose choose, |
| 311 | + const date::time_zone* tz, |
| 312 | + const std::string& timeZoneName) { |
| 313 | + validateRange(date::sys_time<TimeZone::milliseconds>(timestamp)); |
| 314 | + |
| 315 | + // Time zone offsets only have one name. |
| 316 | + if (tz == nullptr) { |
| 317 | + return timeZoneName; |
| 318 | + } |
| 319 | + |
| 320 | + static const auto& timeZoneNames = getTimeZoneNames(); |
| 321 | + auto it = timeZoneNames.find(timeZoneName); |
| 322 | + |
| 323 | + VELOX_CHECK( |
| 324 | + it != timeZoneNames.end(), |
| 325 | + "Unable to find short name for time zone: {}", |
| 326 | + timeZoneName); |
| 327 | + |
| 328 | + // According to the documentation this is how to determine if DST applies to |
| 329 | + // a given timestamp in a given time zone. |
| 330 | + // https://howardhinnant.github.io/date/tz.html#sys_info |
| 331 | + date::local_time<TimeZone::milliseconds> timePoint{timestamp}; |
| 332 | + bool isDst = getZonedTime(tz, timePoint, choose).get_info().save != |
| 333 | + std::chrono::minutes(0); |
| 334 | + |
| 335 | + if constexpr (isLongName) { |
| 336 | + return isDst ? it->second.daylightTimeLongName |
| 337 | + : it->second.standardTimeLongName; |
| 338 | + } else { |
| 339 | + return isDst ? it->second.daylightTimeAbbreviation |
| 340 | + : it->second.standardTimeAbbreviation; |
| 341 | + } |
| 342 | +} |
314 | 343 | } // namespace
|
315 | 344 |
|
316 | 345 | void validateRange(time_point<std::chrono::seconds> timePoint) {
|
@@ -419,58 +448,12 @@ TimeZone::milliseconds TimeZone::to_local(
|
419 | 448 | std::string TimeZone::getShortName(
|
420 | 449 | TimeZone::milliseconds timestamp,
|
421 | 450 | TimeZone::TChoose choose) const {
|
422 |
| - date::local_time<milliseconds> timePoint{timestamp}; |
423 |
| - validateRange(date::sys_time<milliseconds>(timestamp)); |
424 |
| - |
425 |
| - // Time zone offsets only have one name (no abbreviations). |
426 |
| - if (tz_ == nullptr) { |
427 |
| - return timeZoneName_; |
428 |
| - } |
429 |
| - |
430 |
| - return getZonedTime(tz_, timePoint, choose).get_info().abbrev; |
| 451 | + return getName<false>(timestamp, choose, tz_, timeZoneName_); |
431 | 452 | }
|
432 | 453 |
|
433 | 454 | std::string TimeZone::getLongName(
|
434 | 455 | TimeZone::milliseconds timestamp,
|
435 | 456 | TimeZone::TChoose choose) const {
|
436 |
| - static const icu::Locale locale("en", "US"); |
437 |
| - |
438 |
| - validateRange(date::sys_time<milliseconds>(timestamp)); |
439 |
| - |
440 |
| - // Time zone offsets only have one name. |
441 |
| - if (tz_ == nullptr) { |
442 |
| - return timeZoneName_; |
443 |
| - } |
444 |
| - |
445 |
| - // Special case for UTC. ICU uses "GMT" for some reason which is an |
446 |
| - // abbreviation. |
447 |
| - if (timeZoneID_ == 0) { |
448 |
| - return "Coordinated Universal Time"; |
449 |
| - } |
450 |
| - |
451 |
| - // Get the ICU TimeZone by name |
452 |
| - std::unique_ptr<icu::TimeZone> tz(icu::TimeZone::createTimeZone( |
453 |
| - icu::UnicodeString(timeZoneName_.data(), timeZoneName_.length()))); |
454 |
| - VELOX_USER_CHECK_NOT_NULL(tz); |
455 |
| - |
456 |
| - // According to the documentation this is how to determine if DST applies to |
457 |
| - // a given timestamp in a given time zone. |
458 |
| - // https://howardhinnant.github.io/date/tz.html#sys_info |
459 |
| - date::local_time<milliseconds> timePoint{timestamp}; |
460 |
| - bool isDst = getZonedTime(tz_, timePoint, choose).get_info().save != |
461 |
| - std::chrono::minutes(0); |
462 |
| - |
463 |
| - // Construct the long name for the time zone. |
464 |
| - // Note that ICU does not have DST information for many time zones prior to |
465 |
| - // 1970, so it's important to specify it explicitly. |
466 |
| - icu::UnicodeString longName; |
467 |
| - tz->getDisplayName( |
468 |
| - isDst, icu::TimeZone::EDisplayType::LONG, locale, longName); |
469 |
| - |
470 |
| - // Convert the UnicodeString back to a string and write it out |
471 |
| - std::string longNameStr; |
472 |
| - longName.toUTF8String(longNameStr); |
473 |
| - |
474 |
| - return longNameStr; |
| 457 | + return getName<true>(timestamp, choose, tz_, timeZoneName_); |
475 | 458 | }
|
476 | 459 | } // namespace facebook::velox::tz
|
0 commit comments