Commit | Line | Data |
---|---|---|
a386e246 | 1 | /* |
0235b0db | 2 | * SPDX-License-Identifier: MIT |
a386e246 | 3 | * |
0235b0db | 4 | * Copyright (C) 2011-2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
a386e246 SKC |
5 | */ |
6 | ||
0235b0db MJ |
7 | #ifndef _BABELTRACE_UTC_H |
8 | #define _BABELTRACE_UTC_H | |
9 | ||
a386e246 SKC |
10 | #include <time.h> |
11 | ||
12 | /* If set, use GNU or BSD timegm(3) */ | |
13 | #if defined(_BSD_SOURCE) || defined(_SVID_SOURCE) | |
14 | ||
15 | static inline | |
03f61dea | 16 | time_t bt_timegm(struct tm *tm) |
a386e246 SKC |
17 | { |
18 | return timegm(tm); | |
19 | } | |
20 | ||
3d2f08e7 MJ |
21 | #elif defined(__MINGW32__) |
22 | ||
23 | static inline | |
24 | time_t bt_timegm(struct tm *tm) | |
25 | { | |
26 | return _mkgmtime(tm); | |
27 | } | |
28 | ||
a386e246 SKC |
29 | #else |
30 | ||
95abf2a0 | 31 | #include <errno.h> |
a386e246 SKC |
32 | |
33 | /* | |
95abf2a0 MJ |
34 | * This is a simple implementation of timegm() it just turns the "struct tm" into |
35 | * a GMT time_t. It does not normalize any of the fields of the "struct tm", nor | |
36 | * does it set tm_wday or tm_yday. | |
a386e246 SKC |
37 | */ |
38 | ||
95abf2a0 MJ |
39 | static inline |
40 | int bt_leapyear(int year) | |
41 | { | |
42 | return ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)); | |
43 | } | |
44 | ||
a386e246 | 45 | static inline |
03f61dea | 46 | time_t bt_timegm(struct tm *tm) |
a386e246 | 47 | { |
95abf2a0 MJ |
48 | int year, month, total_days; |
49 | ||
50 | int monthlen[2][12] = { | |
51 | /* Days per month for a regular year */ | |
52 | { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, | |
53 | /* Days per month for a leap year */ | |
54 | { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, | |
55 | }; | |
56 | ||
57 | if ((tm->tm_mon >= 12) || | |
58 | (tm->tm_mday >= 32) || | |
59 | (tm->tm_hour >= 24) || | |
60 | (tm->tm_min >= 60) || | |
61 | (tm->tm_sec >= 61)) { | |
62 | errno = EOVERFLOW; | |
63 | return (time_t) -1; | |
64 | } | |
65 | ||
66 | /* Add 365 days for each year since 1970 */ | |
67 | total_days = 365 * (tm->tm_year - 70); | |
68 | ||
69 | /* Add one day for each leap year since 1970 */ | |
70 | for (year = 70; year < tm->tm_year; year++) { | |
71 | if (bt_leapyear(1900 + year)) { | |
72 | total_days++; | |
a386e246 SKC |
73 | } |
74 | } | |
75 | ||
95abf2a0 MJ |
76 | /* Add days for each remaining month */ |
77 | for (month = 0; month < tm->tm_mon; month++) { | |
78 | total_days += monthlen[bt_leapyear(1900 + year)][month]; | |
a386e246 | 79 | } |
95abf2a0 MJ |
80 | |
81 | /* Add remaining days */ | |
82 | total_days += tm->tm_mday - 1; | |
83 | ||
84 | return ((((total_days * 24) + tm->tm_hour) * 60 + tm->tm_min) * 60 + tm->tm_sec); | |
a386e246 SKC |
85 | } |
86 | ||
87 | #endif | |
88 | ||
89 | #endif /* _BABELTRACE_UTC_H */ |