libpurple/util.c

changeset 41249
b147a2ac58f0
parent 41237
5098e0dd3a09
child 41250
e82d07ed6862
equal deleted inserted replaced
41248:f655ed7072b7 41249:b147a2ac58f0
83 83
84 const char * 84 const char *
85 purple_date_format_full(const struct tm *tm) 85 purple_date_format_full(const struct tm *tm)
86 { 86 {
87 return purple_utf8_strftime("%c", tm); 87 return purple_utf8_strftime("%c", tm);
88 }
89
90 /* originally taken from GLib trunk 1-6-11 */
91 /* originally licensed as LGPL 2+ */
92 static time_t
93 mktime_utc(struct tm *tm)
94 {
95 time_t retval;
96
97 #ifndef HAVE_TIMEGM
98 static const gint days_before[] =
99 {
100 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
101 };
102 #endif
103
104 #ifndef HAVE_TIMEGM
105 if (tm->tm_mon < 0 || tm->tm_mon > 11)
106 return (time_t) -1;
107
108 retval = (tm->tm_year - 70) * 365;
109 retval += (tm->tm_year - 68) / 4;
110 retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
111
112 if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
113 retval -= 1;
114
115 retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec;
116 #else
117 retval = timegm (tm);
118 #endif /* !HAVE_TIMEGM */
119
120 return retval;
121 }
122
123 time_t
124 purple_str_to_time(const char *timestamp, gboolean utc,
125 struct tm *tm, long *tz_off, const char **rest)
126 {
127 struct tm t;
128 const gchar *str;
129 gint year = 0;
130 long tzoff = PURPLE_NO_TZ_OFF;
131 time_t retval;
132 gboolean mktime_with_utc = FALSE;
133
134 if (rest != NULL)
135 *rest = NULL;
136
137 g_return_val_if_fail(timestamp != NULL, 0);
138
139 memset(&t, 0, sizeof(struct tm));
140
141 str = timestamp;
142
143 /* Strip leading whitespace */
144 while (g_ascii_isspace(*str))
145 str++;
146
147 if (*str == '\0') {
148 if (rest != NULL) {
149 *rest = str;
150 }
151
152 return 0;
153 }
154
155 if (!g_ascii_isdigit(*str) && *str != '-' && *str != '+') {
156 if (rest != NULL && *str != '\0')
157 *rest = str;
158
159 return 0;
160 }
161
162 /* 4 digit year */
163 if (sscanf(str, "%04d", &year) && year >= 1900) {
164 str += 4;
165
166 if (*str == '-' || *str == '/')
167 str++;
168
169 t.tm_year = year - 1900;
170 }
171
172 /* 2 digit month */
173 if (!sscanf(str, "%02d", &t.tm_mon)) {
174 if (rest != NULL && *str != '\0')
175 *rest = str;
176
177 return 0;
178 }
179
180 str += 2;
181 t.tm_mon -= 1;
182
183 if (*str == '-' || *str == '/')
184 str++;
185
186 /* 2 digit day */
187 if (!sscanf(str, "%02d", &t.tm_mday)) {
188 if (rest != NULL && *str != '\0')
189 *rest = str;
190
191 return 0;
192 }
193
194 str += 2;
195
196 /* Grab the year off the end if there's still stuff */
197 if (*str == '/' || *str == '-') {
198 /* But make sure we don't read the year twice */
199 if (year >= 1900) {
200 if (rest != NULL && *str != '\0')
201 *rest = str;
202
203 return 0;
204 }
205
206 str++;
207
208 if (!sscanf(str, "%04d", &t.tm_year)) {
209 if (rest != NULL && *str != '\0')
210 *rest = str;
211
212 return 0;
213 }
214
215 t.tm_year -= 1900;
216 } else if (*str == 'T' || *str == '.') {
217 str++;
218
219 /* Continue grabbing the hours/minutes/seconds */
220 if ((sscanf(str, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 &&
221 (str += 8)) ||
222 (sscanf(str, "%02d%02d%02d", &t.tm_hour, &t.tm_min, &t.tm_sec) == 3 &&
223 (str += 6)))
224 {
225 gint sign, tzhrs, tzmins;
226
227 if (*str == '.') {
228 /* Cut off those pesky micro-seconds */
229 do {
230 str++;
231 } while (*str >= '0' && *str <= '9');
232 }
233
234 sign = (*str == '+') ? 1 : -1;
235
236 /* Process the timezone */
237 if (*str == '+' || *str == '-') {
238 str++;
239
240 if (((sscanf(str, "%02d:%02d", &tzhrs, &tzmins) == 2 && (str += 5)) ||
241 (sscanf(str, "%02d%02d", &tzhrs, &tzmins) == 2 && (str += 4))))
242 {
243 mktime_with_utc = TRUE;
244 tzoff = tzhrs * 60 * 60 + tzmins * 60;
245 tzoff *= sign;
246 }
247 } else if (*str == 'Z') {
248 /* 'Z' = Zulu = UTC */
249 str++;
250 mktime_with_utc = TRUE;
251 tzoff = 0;
252 }
253
254 if (!mktime_with_utc)
255 {
256 /* No timezone specified. */
257
258 if (utc) {
259 mktime_with_utc = TRUE;
260 tzoff = 0;
261 } else {
262 /* Local Time */
263 t.tm_isdst = -1;
264 }
265 }
266 }
267 }
268
269 if (rest != NULL && *str != '\0') {
270 /* Strip trailing whitespace */
271 while (g_ascii_isspace(*str))
272 str++;
273
274 if (*str != '\0')
275 *rest = str;
276 }
277
278 if (mktime_with_utc)
279 retval = mktime_utc(&t);
280 else
281 retval = mktime(&t);
282
283 if (tm != NULL)
284 *tm = t;
285
286 if (tzoff != PURPLE_NO_TZ_OFF)
287 retval -= tzoff;
288
289 if (tz_off != NULL)
290 *tz_off = tzoff;
291
292 return retval;
293 }
294
295 GDateTime *
296 purple_str_to_date_time(const char *timestamp, gboolean utc)
297 {
298 const gchar *str;
299 gint year = 0;
300 gint month = 0;
301 gint day = 0;
302 gint hour = 0;
303 gint minute = 0;
304 gint seconds = 0;
305 gint microseconds = 0;
306 int chars = 0;
307 GTimeZone *tz = NULL;
308 GDateTime *retval;
309
310 g_return_val_if_fail(timestamp != NULL, NULL);
311
312 str = timestamp;
313
314 /* Strip leading whitespace */
315 while (g_ascii_isspace(*str))
316 str++;
317
318 if (*str == '\0') {
319 return NULL;
320 }
321
322 if (!g_ascii_isdigit(*str) && *str != '-' && *str != '+') {
323 return NULL;
324 }
325
326 /* 4 digit year */
327 if (sscanf(str, "%04d", &year) && year > 0) {
328 str += 4;
329
330 if (*str == '-' || *str == '/')
331 str++;
332 }
333
334 /* 2 digit month */
335 if (!sscanf(str, "%02d", &month)) {
336 return NULL;
337 }
338
339 str += 2;
340
341 if (*str == '-' || *str == '/')
342 str++;
343
344 /* 2 digit day */
345 if (!sscanf(str, "%02d", &day)) {
346 return NULL;
347 }
348
349 str += 2;
350
351 /* Grab the year off the end if there's still stuff */
352 if (*str == '/' || *str == '-') {
353 /* But make sure we don't read the year twice */
354 if (year > 0) {
355 return NULL;
356 }
357
358 str++;
359
360 if (!sscanf(str, "%04d", &year)) {
361 return NULL;
362 }
363 } else if (*str == 'T' || *str == '.') {
364 str++;
365
366 /* Continue grabbing the hours/minutes/seconds */
367 if ((sscanf(str, "%02d:%02d:%02d", &hour, &minute, &seconds) == 3 &&
368 (str += 8)) ||
369 (sscanf(str, "%02d%02d%02d", &hour, &minute, &seconds) == 3 &&
370 (str += 6)))
371 {
372 if (*str == '.') {
373 str++;
374 if (sscanf(str, "%d%n", &microseconds, &chars) == 1) {
375 str += chars;
376 }
377 }
378
379 if (*str) {
380 const gchar *end = str;
381 if (*end == '+' || *end == '-') {
382 end++;
383 }
384
385 while (isdigit(*end) || *end == ':') {
386 end++;
387 }
388
389 if (str != end) {
390 /* Trim anything trailing a purely numeric time zone. */
391 gchar *tzstr = g_strndup(str, end - str);
392 tz = g_time_zone_new_identifier(tzstr);
393 g_free(tzstr);
394 if (tz == NULL) {
395 tz = g_time_zone_new_identifier("UTC");
396 }
397 } else {
398 /* Just try whatever is there. */
399 tz = g_time_zone_new_identifier(str);
400 if (tz == NULL) {
401 tz = g_time_zone_new_identifier("UTC");
402 }
403 }
404 }
405 }
406 }
407
408 if (!tz) {
409 /* No timezone specified. */
410 if (utc) {
411 tz = g_time_zone_new_utc();
412 } else {
413 tz = g_time_zone_new_local();
414 }
415 }
416
417 retval = g_date_time_new(tz, year, month, day, hour, minute,
418 seconds + microseconds * pow(10, -chars));
419 g_time_zone_unref(tz);
420
421 return retval;
422 }
423
424 gint purple_time_parse_month(const char *month_abbr)
425 {
426 const char *months[] = {
427 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
428 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
429 NULL};
430 for (gint month = 0; months[month] != NULL; month++) {
431 if (purple_strequal(month_abbr, months[month])) {
432 return month + 1;
433 }
434 }
435 return 0;
436 } 88 }
437 89
438 /************************************************************************** 90 /**************************************************************************
439 * Path/Filename Functions 91 * Path/Filename Functions
440 **************************************************************************/ 92 **************************************************************************/

mercurial