time_zone_lookup.cc
Go to the documentation of this file.
1 // Copyright 2016 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 #if defined(__ANDROID__)
18 #include <sys/system_properties.h>
19 #if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
20 #include <dlfcn.h>
21 #endif
22 #endif
23 
24 #if defined(__APPLE__)
25 #include <CoreFoundation/CFTimeZone.h>
26 #include <vector>
27 #endif
28 
29 #include <cstdlib>
30 #include <cstring>
31 #include <string>
32 
33 #include "time_zone_fixed.h"
34 #include "time_zone_impl.h"
35 
36 namespace absl {
37 namespace time_internal {
38 namespace cctz {
39 
40 #if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21
41 namespace {
42 // Android 'L' removes __system_property_get() from the NDK, however
43 // it is still a hidden symbol in libc so we use dlsym() to access it.
44 // See Chromium's base/sys_info_android.cc for a similar example.
45 
46 using property_get_func = int (*)(const char*, char*);
47 
48 property_get_func LoadSystemPropertyGet() {
49  int flag = RTLD_LAZY | RTLD_GLOBAL;
50 #if defined(RTLD_NOLOAD)
51  flag |= RTLD_NOLOAD; // libc.so should already be resident
52 #endif
53  if (void* handle = dlopen("libc.so", flag)) {
54  void* sym = dlsym(handle, "__system_property_get");
55  dlclose(handle);
56  return reinterpret_cast<property_get_func>(sym);
57  }
58  return nullptr;
59 }
60 
61 int __system_property_get(const char* name, char* value) {
62  static property_get_func system_property_get = LoadSystemPropertyGet();
63  return system_property_get ? system_property_get(name, value) : -1;
64 }
65 
66 } // namespace
67 #endif
68 
69 std::string time_zone::name() const {
70  return effective_impl().Name();
71 }
72 
74  const time_point<seconds>& tp) const {
75  return effective_impl().BreakTime(tp);
76 }
77 
79  return effective_impl().MakeTime(cs);
80 }
81 
83  civil_transition* trans) const {
84  return effective_impl().NextTransition(tp, trans);
85 }
86 
88  civil_transition* trans) const {
89  return effective_impl().PrevTransition(tp, trans);
90 }
91 
92 std::string time_zone::version() const {
93  return effective_impl().Version();
94 }
95 
96 std::string time_zone::description() const {
97  return effective_impl().Description();
98 }
99 
101  if (impl_ == nullptr) {
102  // Dereferencing an implicit-UTC time_zone is expected to be
103  // rare, so we don't mind paying a small synchronization cost.
104  return *time_zone::Impl::UTC().impl_;
105  }
106  return *impl_;
107 }
108 
109 bool load_time_zone(const std::string& name, time_zone* tz) {
110  return time_zone::Impl::LoadTimeZone(name, tz);
111 }
112 
114  return time_zone::Impl::UTC(); // avoid name lookup
115 }
116 
118  time_zone tz;
119  load_time_zone(FixedOffsetToName(offset), &tz);
120  return tz;
121 }
122 
124  const char* zone = ":localtime";
125 #if defined(__ANDROID__)
126  char sysprop[PROP_VALUE_MAX];
127  if (__system_property_get("persist.sys.timezone", sysprop) > 0) {
128  zone = sysprop;
129  }
130 #endif
131 #if defined(__APPLE__)
132  std::vector<char> buffer;
133  CFTimeZoneRef tz_default = CFTimeZoneCopyDefault();
134  if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) {
135  CFStringEncoding encoding = kCFStringEncodingUTF8;
136  CFIndex length = CFStringGetLength(tz_name);
137  buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1);
138  if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) {
139  zone = &buffer[0];
140  }
141  }
142  CFRelease(tz_default);
143 #endif
144 
145  // Allow ${TZ} to override to default zone.
146  char* tz_env = nullptr;
147 #if defined(_MSC_VER)
148  _dupenv_s(&tz_env, nullptr, "TZ");
149 #else
150  tz_env = std::getenv("TZ");
151 #endif
152  if (tz_env) zone = tz_env;
153 
154  // We only support the "[:]<zone-name>" form.
155  if (*zone == ':') ++zone;
156 
157  // Map "localtime" to a system-specific name, but
158  // allow ${LOCALTIME} to override the default name.
159  char* localtime_env = nullptr;
160  if (strcmp(zone, "localtime") == 0) {
161 #if defined(_MSC_VER)
162  // System-specific default is just "localtime".
163  _dupenv_s(&localtime_env, nullptr, "LOCALTIME");
164 #else
165  zone = "/etc/localtime"; // System-specific default.
166  localtime_env = std::getenv("LOCALTIME");
167 #endif
168  if (localtime_env) zone = localtime_env;
169  }
170 
171  const std::string name = zone;
172 #if defined(_MSC_VER)
173  free(localtime_env);
174  free(tz_env);
175 #endif
176 
177  time_zone tz;
178  load_time_zone(name, &tz); // Falls back to UTC.
179  // TODO: Follow the RFC3339 "Unknown Local Offset Convention" and
180  // arrange for %z to generate "-0000" when we don't know the local
181  // offset because the load_time_zone() failed and we're using UTC.
182  return tz;
183 }
184 
185 } // namespace cctz
186 } // namespace time_internal
187 } // namespace absl
bool next_transition(const time_point< seconds > &tp, civil_transition *trans) const
static bool LoadTimeZone(const std::string &name, time_zone *tz)
time_zone fixed_time_zone(const seconds &offset)
bool NextTransition(const time_point< seconds > &tp, time_zone::civil_transition *trans) const
std::chrono::duration< std::int_fast64_t > seconds
Definition: time_zone.h:37
Definition: algorithm.h:29
time_zone::absolute_lookup BreakTime(const time_point< seconds > &tp) const
size_t value
bool prev_transition(const time_point< seconds > &tp, civil_transition *trans) const
absolute_lookup lookup(const time_point< seconds > &tp) const
char name[1]
Definition: mutex.cc:296
time_zone::civil_lookup MakeTime(const civil_second &cs) const
std::chrono::time_point< std::chrono::system_clock, D > time_point
Definition: time_zone.h:36
std::string FixedOffsetToName(const seconds &offset)
const std::string & Name() const
bool load_time_zone(const std::string &name, time_zone *tz)
std::size_t length
Definition: test_util.cc:52
bool PrevTransition(const time_point< seconds > &tp, time_zone::civil_transition *trans) const


abseil_cpp
Author(s):
autogenerated on Tue Jun 18 2019 19:44:37