1 /*****************************************************************************/
5 /* Make calendar time from broken down time and cleanup */
9 /* (C) 2002 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
42 /*****************************************************************************/
44 /*****************************************************************************/
51 #define JAN_1_1970 4 /* 1/1/1970 is a thursday */
55 static const unsigned char MonthLength [] = {
56 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
58 static const unsigned MonthDays [] = {
59 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
64 /*****************************************************************************/
66 /*****************************************************************************/
70 static unsigned char __fastcall__ IsLeapYear (unsigned Year)
71 /* Returns 1 if the given year is a leap year */
73 return (((Year % 4) == 0) && ((Year % 100) != 0 || (Year % 400) == 0));
78 time_t __fastcall__ mktime (register struct tm* TM)
79 /* Make a time in seconds since 1/1/1970 from the broken down time in TM.
80 * A call to mktime does also correct the time in TM to contain correct
88 /* Check if TM is valid */
95 D = div (TM->tm_sec, 60);
99 if (TM->tm_min + D.quot < 0) {
102 TM->tm_min += D.quot;
103 D = div (TM->tm_min, 60);
107 if (TM->tm_hour + D.quot < 0) {
110 TM->tm_hour += D.quot;
111 D = div (TM->tm_hour, 24);
115 if (TM->tm_mday + D.quot < 0) {
118 TM->tm_mday += D.quot;
120 /* Adjust month and year. This is an iterative process, since changing
121 * the month will change the allowed days for this month.
125 /* Make sure, month is in the range 0..11 */
126 D = div (TM->tm_mon, 12);
128 if (TM->tm_year + D.quot < 0) {
131 TM->tm_year += D.quot;
133 /* Now check if mday is in the correct range, if not, correct month
134 * and eventually year and repeat the process.
136 if (TM->tm_mon == FEBRUARY && IsLeapYear (TM->tm_year + 1900)) {
139 Max = MonthLength[TM->tm_mon];
141 if (TM->tm_mday > Max) {
142 /* Must correct month and eventually, year */
143 if (TM->tm_mon == DECEMBER) {
144 TM->tm_mon = JANUARY;
156 /* Ok, all time/date fields are now correct. Calculate the days in this
159 TM->tm_yday = MonthDays[TM->tm_mon] + TM->tm_mday - 1;
160 if (TM->tm_mon > FEBRUARY && IsLeapYear (TM->tm_year + 1900)) {
164 /* Calculate days since 1/1/1970. In the complete epoch (1/1/1970 to
165 * somewhere in 2038) all years dividable by 4 are leap years, so
166 * dividing by 4 gives the days that must be added cause of leap years.
167 * (and the last leap year before 1970 was 1968)
169 DayCount = ((unsigned) (TM->tm_year-70)) * 365U +
170 (((unsigned) (TM->tm_year-(68+1))) / 4) +
173 /* Calculate the weekday */
174 TM->tm_wday = (JAN_1_1970 + DayCount) % 7;
176 /* No (US) daylight saving (for now) */
179 /* Return seconds since 1970 */
180 return DayCount * 86400UL +
181 ((unsigned) TM->tm_hour) * 3600UL +
182 ((unsigned) TM->tm_min) * 60U +
183 ((unsigned) TM->tm_sec);