time_zone_lookup.cc
Go to the documentation of this file.
00001 // Copyright 2016 Google Inc. All Rights Reserved.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //   https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 //   Unless required by applicable law or agreed to in writing, software
00010 //   distributed under the License is distributed on an "AS IS" BASIS,
00011 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 //   See the License for the specific language governing permissions and
00013 //   limitations under the License.
00014 
00015 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
00016 
00017 #if defined(__ANDROID__)
00018 #include <sys/system_properties.h>
00019 #if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
00020 #include <dlfcn.h>
00021 #endif
00022 #endif
00023 
00024 #if defined(__APPLE__)
00025 #include <CoreFoundation/CFTimeZone.h>
00026 #include <vector>
00027 #endif
00028 
00029 #include <cstdlib>
00030 #include <cstring>
00031 #include <string>
00032 
00033 #include "time_zone_fixed.h"
00034 #include "time_zone_impl.h"
00035 
00036 namespace absl {
00037 namespace time_internal {
00038 namespace cctz {
00039 
00040 #if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21
00041 namespace {
00042 // Android 'L' removes __system_property_get() from the NDK, however
00043 // it is still a hidden symbol in libc so we use dlsym() to access it.
00044 // See Chromium's base/sys_info_android.cc for a similar example.
00045 
00046 using property_get_func = int (*)(const char*, char*);
00047 
00048 property_get_func LoadSystemPropertyGet() {
00049   int flag = RTLD_LAZY | RTLD_GLOBAL;
00050 #if defined(RTLD_NOLOAD)
00051   flag |= RTLD_NOLOAD;  // libc.so should already be resident
00052 #endif
00053   if (void* handle = dlopen("libc.so", flag)) {
00054     void* sym = dlsym(handle, "__system_property_get");
00055     dlclose(handle);
00056     return reinterpret_cast<property_get_func>(sym);
00057   }
00058   return nullptr;
00059 }
00060 
00061 int __system_property_get(const char* name, char* value) {
00062   static property_get_func system_property_get = LoadSystemPropertyGet();
00063   return system_property_get ? system_property_get(name, value) : -1;
00064 }
00065 
00066 }  // namespace
00067 #endif
00068 
00069 std::string time_zone::name() const {
00070   return effective_impl().Name();
00071 }
00072 
00073 time_zone::absolute_lookup time_zone::lookup(
00074     const time_point<seconds>& tp) const {
00075   return effective_impl().BreakTime(tp);
00076 }
00077 
00078 time_zone::civil_lookup time_zone::lookup(const civil_second& cs) const {
00079   return effective_impl().MakeTime(cs);
00080 }
00081 
00082 bool time_zone::next_transition(const time_point<seconds>& tp,
00083                                 civil_transition* trans) const {
00084   return effective_impl().NextTransition(tp, trans);
00085 }
00086 
00087 bool time_zone::prev_transition(const time_point<seconds>& tp,
00088                                 civil_transition* trans) const {
00089   return effective_impl().PrevTransition(tp, trans);
00090 }
00091 
00092 std::string time_zone::version() const {
00093   return effective_impl().Version();
00094 }
00095 
00096 std::string time_zone::description() const {
00097   return effective_impl().Description();
00098 }
00099 
00100 const time_zone::Impl& time_zone::effective_impl() const {
00101   if (impl_ == nullptr) {
00102     // Dereferencing an implicit-UTC time_zone is expected to be
00103     // rare, so we don't mind paying a small synchronization cost.
00104     return *time_zone::Impl::UTC().impl_;
00105   }
00106   return *impl_;
00107 }
00108 
00109 bool load_time_zone(const std::string& name, time_zone* tz) {
00110   return time_zone::Impl::LoadTimeZone(name, tz);
00111 }
00112 
00113 time_zone utc_time_zone() {
00114   return time_zone::Impl::UTC();  // avoid name lookup
00115 }
00116 
00117 time_zone fixed_time_zone(const seconds& offset) {
00118   time_zone tz;
00119   load_time_zone(FixedOffsetToName(offset), &tz);
00120   return tz;
00121 }
00122 
00123 time_zone local_time_zone() {
00124   const char* zone = ":localtime";
00125 #if defined(__ANDROID__)
00126   char sysprop[PROP_VALUE_MAX];
00127   if (__system_property_get("persist.sys.timezone", sysprop) > 0) {
00128     zone = sysprop;
00129   }
00130 #endif
00131 #if defined(__APPLE__)
00132   std::vector<char> buffer;
00133   CFTimeZoneRef tz_default = CFTimeZoneCopyDefault();
00134   if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) {
00135     CFStringEncoding encoding = kCFStringEncodingUTF8;
00136     CFIndex length = CFStringGetLength(tz_name);
00137     buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1);
00138     if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) {
00139       zone = &buffer[0];
00140     }
00141   }
00142   CFRelease(tz_default);
00143 #endif
00144 
00145   // Allow ${TZ} to override to default zone.
00146   char* tz_env = nullptr;
00147 #if defined(_MSC_VER)
00148   _dupenv_s(&tz_env, nullptr, "TZ");
00149 #else
00150   tz_env = std::getenv("TZ");
00151 #endif
00152   if (tz_env) zone = tz_env;
00153 
00154   // We only support the "[:]<zone-name>" form.
00155   if (*zone == ':') ++zone;
00156 
00157   // Map "localtime" to a system-specific name, but
00158   // allow ${LOCALTIME} to override the default name.
00159   char* localtime_env = nullptr;
00160   if (strcmp(zone, "localtime") == 0) {
00161 #if defined(_MSC_VER)
00162     // System-specific default is just "localtime".
00163     _dupenv_s(&localtime_env, nullptr, "LOCALTIME");
00164 #else
00165     zone = "/etc/localtime";  // System-specific default.
00166     localtime_env = std::getenv("LOCALTIME");
00167 #endif
00168     if (localtime_env) zone = localtime_env;
00169   }
00170 
00171   const std::string name = zone;
00172 #if defined(_MSC_VER)
00173   free(localtime_env);
00174   free(tz_env);
00175 #endif
00176 
00177   time_zone tz;
00178   load_time_zone(name, &tz);  // Falls back to UTC.
00179   // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and
00180   // arrange for %z to generate "-0000" when we don't know the local
00181   // offset because the load_time_zone() failed and we're using UTC.
00182   return tz;
00183 }
00184 
00185 }  // namespace cctz
00186 }  // namespace time_internal
00187 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15