1 #include "config.h"
2
3 #if IS_LINUX
4 /* Linux cheats AC_CHECK_FUNCS(strptime_l), sigh. */
5 #define THREAD_SAFE 0
6 #define _XOPEN_SOURCE
7 #define _BSD_SOURCE
8 #elif HAVE_STRPTIME_L
9 #define THREAD_SAFE 1
10 #define _GNU_SOURCE
11 #else
12 #define THREAD_SAFE 0
13 #endif
14
15 #include <string.h>
16 #include <time.h>
17 #include <locale.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20
21 #if defined(_WIN32)
22 #include "win_patch.h"
23 #endif // _WIN32
24
25 #if THREAD_SAFE
26 #if HAVE_XLOCALE_H
27 #include <xlocale.h>
28 #endif
29
30 locale_t c_locale = NULL;
31
init_locale()32 void init_locale() {
33 if (c_locale == NULL) c_locale = newlocale(LC_TIME_MASK, "C", NULL);
34 }
35 #else
init_locale()36 void init_locale() {
37 static int initialized = 0;
38 if (initialized == 0) {
39 setlocale(LC_TIME, "C");
40 initialized = 1;
41 }
42 }
43 #endif
44
45 /*
46 * Set the value of the TZ environment variable to UTC
47 * and return the old value.
48 */
set_tz_utc()49 char *set_tz_utc() {
50 char *tz;
51 tz = getenv("TZ");
52 #if defined(_WIN32)
53 _patch_setenv("TZ", "UTC", 1);
54 #else
55 setenv("TZ", "", 1);
56 #endif
57 tzset();
58 return tz;
59 }
60
61 /*
62 * Set the value of the TZ environment variable to tz or
63 * unset the variable if tz is null;
64 */
set_tz(char * local_tz)65 void set_tz(char *local_tz) {
66 if (local_tz) {
67 #if defined(_WIN32)
68 _patch_setenv("TZ", local_tz, 1);
69 #else
70 setenv("TZ", local_tz, 1);
71 #endif
72 } else {
73 #if defined(_WIN32)
74 _patch_unsetenv("TZ");
75 #else
76 unsetenv("TZ");
77 #endif
78 }
79 tzset();
80 }
81
c_parse_unix_time(char * fmt,char * src)82 time_t c_parse_unix_time(char *fmt, char *src) {
83 struct tm dst;
84 init_locale();
85 memset(&dst, 0, sizeof(struct tm));
86 #if THREAD_SAFE
87 strptime_l(src, fmt, &dst, c_locale);
88 #else
89 strptime(src, fmt, &dst);
90 #endif
91 return mktime(&dst);
92 }
93
94 #if !defined(HAVE_TIMEGM)
95 /* This part is for Solaris that doesn't have timegm.
96 * The copyright notice of timegm and is_leap is as below:
97 *
98 * Copyright (c) 1997 Kungliga Tekniska H.gskolan
99 * (Royal Institute of Technology, Stockholm, Sweden).
100 * All rights reserved.
101 */
102
103 static time_t
timegm(struct tm * tm)104 timegm (struct tm *tm)
105 {
106 static const unsigned ndays[2][12] ={
107 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
108 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
109 time_t res = 0;
110 unsigned i;
111
112 for (i = 70; i < tm->tm_year; ++i)
113 res += isleap(i + 1900) ? 366 : 365;
114
115 for (i = 0; i < tm->tm_mon; ++i)
116 res += ndays[isleap(tm->tm_year + 1900)][i];
117 res += tm->tm_mday - 1;
118 res *= 24;
119 res += tm->tm_hour;
120 res *= 60;
121 res += tm->tm_min;
122 res *= 60;
123 res += tm->tm_sec;
124 return res;
125 }
126 #endif /* HAVE_TIMEGM */
127
c_parse_unix_time_gmt(char * fmt,char * src)128 time_t c_parse_unix_time_gmt(char *fmt, char *src) {
129 struct tm dst;
130 char *local_tz;
131 init_locale();
132 memset(&dst, 0, sizeof(struct tm));
133 local_tz = set_tz_utc();
134 #if THREAD_SAFE
135 strptime_l(src, fmt, &dst, c_locale);
136 #else
137 strptime(src, fmt, &dst);
138 #endif
139 set_tz(local_tz);
140 return timegm(&dst);
141 }
142
c_format_unix_time(char * fmt,time_t src,char * dst,int siz)143 size_t c_format_unix_time(char *fmt, time_t src, char* dst, int siz) {
144 struct tm tim;
145 init_locale();
146 localtime_r(&src, &tim);
147 #if THREAD_SAFE
148 #if defined(_WIN32)
149 return _patch_strftime_l(dst, siz, fmt, &tim, c_locale);
150 #else
151 return strftime_l(dst, siz, fmt, &tim, c_locale);
152 #endif // _WIN32
153 #else
154 #if defined(_WIN32)
155 return _patch_strftime(dst, siz, fmt, &tim);
156 #else
157 return strftime(dst, siz, fmt, &tim);
158 #endif // _WIN32
159 #endif
160 }
161
c_format_unix_time_gmt(char * fmt,time_t src,char * dst,int siz)162 size_t c_format_unix_time_gmt(char *fmt, time_t src, char* dst, int siz) {
163 struct tm tim;
164 char *local_tz;
165 size_t dst_size;
166
167 init_locale();
168 gmtime_r(&src, &tim);
169
170 local_tz = set_tz_utc();
171 #if THREAD_SAFE
172 #if defined(_WIN32)
173 dst_size = _patch_strftime_l(dst, siz, fmt, &tim, c_locale);
174 #else
175 dst_size = strftime_l(dst, siz, fmt, &tim, c_locale);
176 #endif // _WIN32
177 #else
178 #if defined(_WIN32)
179 dst_size = _patch_strftime(dst, siz, fmt, &tim);
180 #else
181 dst_size = strftime(dst, siz, fmt, &tim);
182 #endif // _WIN32
183 #endif
184 set_tz(local_tz);
185 return dst_size;
186 }
187