Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
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
00043
00044
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;
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 }
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
00103
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();
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
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
00155 if (*zone == ':') ++zone;
00156
00157
00158
00159 char* localtime_env = nullptr;
00160 if (strcmp(zone, "localtime") == 0) {
00161 #if defined(_MSC_VER)
00162
00163 _dupenv_s(&localtime_env, nullptr, "LOCALTIME");
00164 #else
00165 zone = "/etc/localtime";
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);
00179
00180
00181
00182 return tz;
00183 }
00184
00185 }
00186 }
00187 }