Retrieve the timezone bias in mktime via GetTimeZoneInformation
[reactos.git] / reactos / lib / sdk / crt / time / mktime.c
1 /*
2 * COPYRIGHT: LGPL, See LGPL.txt in the top level directory
3 * PROJECT: ReactOS CRT library
4 * FILE: lib/sdk/crt/time/mktime.c
5 * PURPOSE: Implementation of mktime, _mkgmtime
6 * PROGRAMERS: Timo Kreuzer
7 */
8 #include <precomp.h>
9 #include "bitsfixup.h"
10
11 #define MAX_32BIT_TIME 0xFFFFFFFFULL
12
13 static int g_monthdays[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
14
15 __time64_t
16 mktime_worker(struct tm * ptm, int utc)
17 {
18 struct tm *ptm2;
19 __time64_t time;
20 int mons, years, leapyears;
21 TIME_ZONE_INFORMATION tzi;
22 DWORD ret;
23
24 /* Normalize year and month */
25 if (ptm->tm_mon < 0)
26 {
27 mons = -ptm->tm_mon - 1;
28 ptm->tm_year -= 1 + mons / 12;
29 ptm->tm_mon = 11 - (mons % 12);
30 }
31 else if (ptm->tm_mon > 11)
32 {
33 mons = ptm->tm_mon;
34 ptm->tm_year += (mons / 12);
35 ptm->tm_mon = mons % 12;
36 }
37
38 /* Is it inside margins */
39 if (ptm->tm_year < 70 || ptm->tm_year > 139) // FIXME: max year for 64 bits
40 {
41 return -1;
42 }
43
44 years = ptm->tm_year - 70;
45
46 /* Number of leapyears passed since 1970 */
47 leapyears = (years + 1) / 4;
48
49 /* Calculate days up to 1st of Jan */
50 time = years * 365 + leapyears;
51
52 /* Calculate days up to 1st of month */
53 time += g_monthdays[ptm->tm_mon];
54
55 /* Check if we need to add a leap day */
56 if (((years + 2) % 4) == 0)
57 {
58 if (ptm->tm_mon > 2)
59 {
60 time++;
61 }
62 }
63
64 time += ptm->tm_mday - 1;
65
66 time *= 24;
67 time += ptm->tm_hour;
68
69 time *= 60;
70 time += ptm->tm_min;
71
72 time *= 60;
73 time += ptm->tm_sec;
74
75 if (time < 0)
76 {
77 return -1;
78 }
79
80 /* Finally get normalized tm struct */
81 ptm2 = _gmtime64(&time);
82 if (!ptm2)
83 {
84 return -1;
85 }
86 *ptm = *ptm2;
87
88 /* Finally adjust by the difference to GMT in seconds */
89 ret = GetTimeZoneInformation(&tzi);
90 if (ret != TIME_ZONE_ID_INVALID)
91 {
92 time += tzi.Bias * 60;
93 }
94
95 return time;
96 }
97
98 /* int tm_sec;
99 int tm_min;
100 int tm_hour;
101 int tm_mday;
102 int tm_mon;
103 int tm_year;
104 int tm_wday;
105 int tm_yday;
106 int tm_isdst;
107 */
108
109 /**
110 * \name _mkgmtime
111 *
112 */
113 time_t
114 _mkgmtime(struct tm *ptm)
115 {
116 time_t time = mktime_worker(ptm, 1);
117 return (time > MAX_32BIT_TIME) ? -1 : time;
118 }
119
120 time_t
121 mktime(struct tm *ptm)
122 {
123 time_t time = mktime_worker(ptm, 0);
124 return (time > MAX_32BIT_TIME) ? -1 : time;
125 }
126
127 __time32_t
128 _mkgmtime32(struct tm *ptm)
129 {
130 time_t time = mktime_worker(ptm, 1);
131 return (time > MAX_32BIT_TIME) ? -1 : time;
132 }
133
134 __time32_t
135 _mktime32(struct tm *ptm)
136 {
137 time_t time = mktime_worker(ptm, 0);
138 return (time > MAX_32BIT_TIME) ? -1 : time;
139 }
140
141 __time64_t
142 _mkgmtime64(struct tm *ptm)
143 {
144 return mktime_worker(ptm, 1);
145 }
146
147 __time64_t
148 _mktime64(struct tm *ptm)
149 {
150 return mktime_worker(ptm, 0);
151 }