Skip to content

Commit 4d611b8

Browse files
committed
Fall back from /etc/localtime as a symlink to localtime function
1 parent 3656a37 commit 4d611b8

File tree

1 file changed

+34
-22
lines changed

1 file changed

+34
-22
lines changed

CoreFoundation/NumberDate.subproj/CFTimeZone.c

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ struct tzhead {
5757
};
5858
#endif
5959

60+
#include <time.h>
61+
6062
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED || DEPLOYMENT_TARGET_LINUX
6163
#define TZZONELINK TZDEFAULT
6264
#define TZZONEINFO TZDIR "/"
@@ -710,8 +712,9 @@ void __InitTZStrings(void) {
710712
static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
711713
CFTimeZoneRef result = NULL;
712714

713-
#if DEPLOYMENT_TARGET_WINDOWS
714715
CFStringRef name = NULL;
716+
717+
#if DEPLOYMENT_TARGET_WINDOWS
715718
TIME_ZONE_INFORMATION tzi = { 0 };
716719
DWORD rval = GetTimeZoneInformation(&tzi);
717720
if (rval != TIME_ZONE_ID_INVALID) {
@@ -729,40 +732,49 @@ static CFTimeZoneRef __CFTimeZoneCreateSystem(void) {
729732
} else {
730733
CFLog(kCFLogLevelError, CFSTR("Couldn't get time zone information error %d"), GetLastError());
731734
}
732-
if (name) {
733735
#else
734736
const char *tzenv;
735737
int ret;
736738
char linkbuf[CFMaxPathSize];
737-
739+
738740
tzenv = __CFgetenv("TZFILE");
739741
if (NULL != tzenv) {
740-
CFStringRef name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
741-
result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
742-
CFRelease(name);
743-
if (result) return result;
742+
CFStringRef name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
743+
result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
744+
CFRelease(name);
745+
if (result) return result;
744746
}
745747
tzenv = __CFgetenv("TZ");
746748
if (NULL != tzenv) {
747-
CFStringRef name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
748-
result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, true);
749-
CFRelease(name);
750-
if (result) return result;
749+
CFStringRef name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)tzenv, strlen(tzenv), kCFStringEncodingUTF8, false);
750+
result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, true);
751+
CFRelease(name);
752+
if (result) return result;
751753
}
752754
ret = readlink(TZZONELINK, linkbuf, sizeof(linkbuf));
753755
if (0 < ret) {
754-
CFStringRef name;
755-
linkbuf[ret] = '\0';
756-
if (strncmp(linkbuf, TZZONEINFO, sizeof(TZZONEINFO) - 1) == 0) {
757-
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + sizeof(TZZONEINFO) - 1, strlen(linkbuf) - sizeof(TZZONEINFO) + 1, kCFStringEncodingUTF8, false);
758-
} else {
759-
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
760-
}
756+
CFStringRef name;
757+
linkbuf[ret] = '\0';
758+
if (strncmp(linkbuf, TZZONEINFO, sizeof(TZZONEINFO) - 1) == 0) {
759+
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf + sizeof(TZZONEINFO) - 1, strlen(linkbuf) - sizeof(TZZONEINFO) + 1, kCFStringEncodingUTF8, false);
760+
} else {
761+
name = CFStringCreateWithBytes(kCFAllocatorSystemDefault, (uint8_t *)linkbuf, strlen(linkbuf), kCFStringEncodingUTF8, false);
762+
}
763+
} else {
764+
// TODO: This can still fail on Linux if the time zone is not recognized by ICU later
765+
// Try localtime
766+
tzset();
767+
time_t t = time(NULL);
768+
struct tm lt = {0};
769+
localtime_r(&t, &lt);
770+
771+
name = CFStringCreateWithCString(kCFAllocatorSystemDefault, lt.tm_zone, kCFStringEncodingUTF8);
772+
}
761773
#endif
762-
763-
result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
764-
CFRelease(name);
765-
if (result) return result;
774+
if (name) {
775+
result = CFTimeZoneCreateWithName(kCFAllocatorSystemDefault, name, false);
776+
CFRelease(name);
777+
if (result) return result;
766778
}
767779
return CFTimeZoneCreateWithTimeIntervalFromGMT(kCFAllocatorSystemDefault, 0.0);
768780
}

0 commit comments

Comments
 (0)