619a7009b533300c197fc84e5e40f0b3368a5823
[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
22 /* Normalize year and month */
23 if (ptm->tm_mon < 0)
24 {
25 mons = -ptm->tm_mon - 1;
26 ptm->tm_year -= 1 + mons / 12;
27 ptm->tm_mon = 11 - (mons % 12);
28 }
29 else if (ptm->tm_mon > 11)
30 {
31 mons = ptm->tm_mon;
32 ptm->tm_year += (mons / 12);
33 ptm->tm_mon = mons % 12;
34 }
35
36 /* Is it inside margins */
37 if (ptm->tm_year < 70 || ptm->tm_year > 139) // FIXME: max year for 64 bits
38 {
39 return -1;
40 }
41
42 years = ptm->tm_year - 70;
43
44 /* Number of leapyears passed since 1970 */
45 leapyears = (years + 1) / 4;
46
47 /* Calculate days up to 1st of Jan */
48 time = years * 365 + leapyears;
49
50 /* Calculate days up to 1st of month */
51 time += g_monthdays[ptm->tm_mon];
52
53 /* Check if we need to add a leap day */
54 if (((years + 2) % 4) == 0)
55 {
56 if (ptm->tm_mon > 2)
57 {
58 time++;
59 }
60 }
61
62 time += ptm->tm_mday - 1;
63
64 time *= 24;
65 time += ptm->tm_hour;
66
67 time *= 60;
68 time += ptm->tm_min;
69
70 time *= 60;
71 time += ptm->tm_sec;
72
73 if (time < 0)
74 {
75 return -1;
76 }
77
78 /* Finally get normalized tm struct */
79 ptm2 = _gmtime64(&time);
80 if (!ptm2)
81 {
82 return -1;
83 }
84 *ptm = *ptm2;
85
86 /* Finally adjust by the difference to GMT in seconds */
87 time += _timezone;
88
89 return time;
90 }
91
92 /* int tm_sec;
93 int tm_min;
94 int tm_hour;
95 int tm_mday;
96 int tm_mon;
97 int tm_year;
98 int tm_wday;
99 int tm_yday;
100 int tm_isdst;
101 */
102
103 /**
104 * \name _mkgmtime
105 *
106 */
107 time_t
108 _mkgmtime(struct tm *ptm)
109 {
110 time_t time = mktime_worker(ptm, 1);
111 return (time > MAX_32BIT_TIME) ? -1 : time;
112 }
113
114 time_t
115 mktime(struct tm *ptm)
116 {
117 time_t time = mktime_worker(ptm, 0);
118 return (time > MAX_32BIT_TIME) ? -1 : time;
119 }
120
121 __time32_t
122 _mkgmtime32(struct tm *ptm)
123 {
124 time_t time = mktime_worker(ptm, 1);
125 return (time > MAX_32BIT_TIME) ? -1 : time;
126 }
127
128 __time32_t
129 _mktime32(struct tm *ptm)
130 {
131 time_t time = mktime_worker(ptm, 0);
132 return (time > MAX_32BIT_TIME) ? -1 : time;
133 }
134
135 __time64_t
136 _mkgmtime64(struct tm *ptm)
137 {
138 return mktime_worker(ptm, 1);
139 }
140
141 __time64_t
142 _mktime64(struct tm *ptm)
143 {
144 return mktime_worker(ptm, 0);
145 }