From c063f5d0c3e3adcc5c3a7a183092d6f48bf4332c Mon Sep 17 00:00:00 2001 From: Filip Filmar Date: Fri, 17 Jan 2020 00:37:35 +0000 Subject: [PATCH] [i18n] Replaces fuchsia.deprecatedtimezone The FIDL library fuchsia.deprecatedtimezone is going away. There are different and better ways to obtain the same functionality. Fixes #39650 Change-Id: If4e4234568c276d3cd2be34863f00165b6e97e0e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/129005 Commit-Queue: Filip Filmar Reviewed-by: Martin Kustermann --- runtime/vm/BUILD.gn | 6 ++-- runtime/vm/os_fuchsia.cc | 59 ++++++++++++++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn index d622a6e4ca11a..f0c83243bb0e9 100644 --- a/runtime/vm/BUILD.gn +++ b/runtime/vm/BUILD.gn @@ -70,16 +70,14 @@ library_for_all_configs("libdart_vm") { if (is_fuchsia) { if (using_fuchsia_sdk) { extra_deps += [ - "$fuchsia_sdk_root/fidl:fuchsia.deprecatedtimezone", + "$fuchsia_sdk_root/fidl:fuchsia.intl", "$fuchsia_sdk_root/pkg:sys_cpp", "$fuchsia_sdk_root/pkg:trace-engine", ] } else { extra_deps += [ - # TODO(US-399): Remove time_service specific code when it is no longer - # necessary. + "//sdk/fidl/fuchsia.intl", "//sdk/lib/sys/cpp", - "//sdk/fidl/fuchsia.deprecatedtimezone", "//zircon/public/lib/fbl", "//zircon/public/lib/trace-engine", diff --git a/runtime/vm/os_fuchsia.cc b/runtime/vm/os_fuchsia.cc index 05985abed4926..6e208a9018e9a 100644 --- a/runtime/vm/os_fuchsia.cc +++ b/runtime/vm/os_fuchsia.cc @@ -11,13 +11,16 @@ #include #include -#include +#include #include #include #include #include #include +#include "third_party/icu/source/common/unicode/errorcode.h" +#include "third_party/icu/source/i18n/unicode/timezone.h" + #include "platform/assert.h" #include "vm/zone.h" @@ -61,33 +64,65 @@ intptr_t OS::ProcessId() { return static_cast(getpid()); } +// This is the default timezone returned if it could not be obtained. For +// Fuchsia, the default device timezone is always UTC. +static const char[] kDefaultTimezone = "UTC"; + // TODO(FL-98): Change this to talk to fuchsia.dart to get timezone service to // directly get timezone. // // Putting this hack right now due to CP-120 as I need to remove // component:ConnectToEnvironmentServices and this is the only thing that is // blocking it and FL-98 will take time. -static fuchsia::deprecatedtimezone::TimezoneSyncPtr tz; +static fuchsia::intl::PropertyProviderSyncPtr property_provider; + +// 1000 milliseconds do one second make. +static const int32_t kMSPerSec = 1000; static zx_status_t GetLocalAndDstOffsetInSeconds(int64_t seconds_since_epoch, int32_t* local_offset, int32_t* dst_offset) { - zx_status_t status = tz->GetTimezoneOffsetMinutes(seconds_since_epoch * 1000, - local_offset, dst_offset); - if (status != ZX_OK) { - return status; + const char* timezone_id = GetTimeZoneName(seconds_since_epoch); + std::unique_ptr timezone( + icu::TimeZone::createTimeZone(timezone_id)); + UErrorCode error = U_ZERO_ERROR; + const auto ms_since_epoch = + static_cast(kMSPerSec * seconds_since_epoch); + // The units of time that local_offset and dst_offset are returned from this + // function is, usefully, not documented, but it seems that the units are + // milliseconds. Add these variables here for clarity. + int32_t local_offset_ms = 0; + int32_t dst_offset_ms = 0; + timezone->getOffset(ms_since_epoch, /*local_time=*/false, local_offset_ms, + dst_offset_ms, error); + if (error != U_ZERO_ERROR) { + icu::ErrorCode icu_error; + icu_error.set(error); + // Sadly there is no way to report the actual error. Next best thing is to + // log. On the upside, a direct call to timezone->getOffset should fail + // rarely, so this should not amount to log spam. + LOG(ERROR) << "could not get DST offset: " << icu_error.errorName(); + return ZX_ERR_INTERNAL; } - *local_offset *= 60; - *dst_offset *= 60; + // We must return offset in seconds, so convert. + *local_offset = local_offset_ms / kMSPerSec; + *dst_offset = dst_offset_ms / kMSPerSec; return ZX_OK; } const char* OS::GetTimeZoneName(int64_t seconds_since_epoch) { // TODO(abarth): Handle time zone changes. static const auto* tz_name = new std::string([] { - std::string result; - tz->GetTimezoneId(&result); - return result; + fuchsia::intl::Profile profile; + zx_status_t status = property_provider->GetProfile(&profile); + if (status != ZX_OK) { + return kDefaultTimezone; + } + const std::vector& tzs = profile.time_zones(); + if (tzs.empty()) { + return kDefaultTimezone; + } + return tzs[0].id; }()); return tz_name->c_str(); } @@ -265,7 +300,7 @@ void OS::PrintErr(const char* format, ...) { void OS::Init() { InitializeTZData(); auto services = sys::ServiceDirectory::CreateFromNamespace(); - services->Connect(tz.NewRequest()); + services->Connect(property_provider.NewRequest()); } void OS::Cleanup() {}