e48bcdcc930e20407031ac7c307b0df097fe1103
[reactos.git] / reactos / lib / sdk / crt / time_new / gmtime.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CRT library
4 * FILE: lib/sdk/crt/time/gmtime.c
5 * PURPOSE: Implementation of gmtime, _gmtime32, _gmtime64
6 * PROGRAMERS: Timo Kreuzer
7 */
8 #include <precomp.h>
9
10 unsigned int g_monthdays[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
11 unsigned int g_lpmonthdays[13] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
12
13 struct tm *
14 _gmtime_worker(struct tm *ptm, __time64_t time, int do_dst)
15 {
16 unsigned int days, daystoyear, dayinyear, leapdays, leapyears, years, month;
17 unsigned int secondinday, secondinhour;
18 unsigned int *padays;
19
20 if (time < 0)
21 {
22 return 0;
23 }
24
25 /* Divide into date and time */
26 days = time / SECONDSPERDAY;
27 secondinday = time % SECONDSPERDAY;
28
29 /* Shift to days from 1.1.1601 */
30 days += DIFFDAYS;
31
32 /* Calculate leap days passed till today */
33 leapdays = leapdays_passed(days);
34
35 /* Calculate number of full leap years passed */
36 leapyears = leapyears_passed(days);
37
38 /* Are more leap days passed than leap years? */
39 if (leapdays > leapyears)
40 {
41 /* Yes, we're in a leap year */
42 padays = g_lpmonthdays;
43 }
44 else
45 {
46 /* No, normal year */
47 padays = g_monthdays;
48 }
49
50 /* Calculate year */
51 years = (days - leapdays) / 365;
52 ptm->tm_year = years - 299;
53
54 /* Calculate number of days till 1.1. of this year */
55 daystoyear = years * 365 + leapyears;
56
57 /* Calculate the day in this year */
58 dayinyear = days - daystoyear;
59
60 /* Shall we do DST corrections? */
61 ptm->tm_isdst = 0;
62 if (do_dst)
63 {
64 unsigned int yeartime = dayinyear * SECONDSPERDAY + secondinday ;
65 if (yeartime >= dst_begin && yeartime <= dst_end) // FIXME! DST in winter
66 {
67 time -= _dstbias;
68 days = time / SECONDSPERDAY + DIFFDAYS;
69 dayinyear = days - daystoyear;
70 ptm->tm_isdst = 1;
71 }
72 }
73
74 ptm->tm_yday = dayinyear;
75
76 /* dayinyear < 366 => terminates with i <= 11 */
77 for (month = 0; dayinyear >= padays[month+1]; month++)
78 ;
79
80 /* Set month and day in month */
81 ptm->tm_mon = month;
82 ptm->tm_mday = 1 + dayinyear - padays[month];
83
84 /* Get weekday */
85 ptm->tm_wday = (days + 4) % 7;
86
87 /* Calculate hour and second in hour */
88 ptm->tm_hour = secondinday / SECONDSPERHOUR;
89 secondinhour = secondinday % SECONDSPERHOUR;
90
91 /* Calculate minute and second */
92 ptm->tm_min = secondinhour / 60;
93 ptm->tm_sec = secondinhour % 60;
94
95 return ptm;
96 }
97
98 /******************************************************************************
99 * \name _gmtime64
100 * \brief
101 * \param ptime Pointer to a variable of type __time64_t containing the time.
102 */
103 struct tm *
104 _gmtime64(const __time64_t * ptime)
105 {
106 PTHREADDATA pThreadData;
107 struct tm *ptm;
108 __time64_t time = *ptime;
109
110 /* Validate parameters */
111 if (time < 0)
112 {
113 return 0;
114 }
115
116 /* Get pointer to TLS tm buffer */
117 pThreadData = GetThreadData();
118 ptm = &pThreadData->tmbuf;
119
120 /* Use _gmtime_worker to do the ral work */
121 return _gmtime_worker(ptm, time, 0);
122 }
123
124 /******************************************************************************
125 * \name _gmtime32
126 * \brief
127 * \param ptime Pointer to a variable of type __time32_t containing the time.
128 */
129 struct tm *
130 _gmtime32(const __time32_t * ptime)
131 {
132 __time64_t time64 = (__time64_t)*ptime;
133 return _gmtime64(&time64);
134 }
135
136 /******************************************************************************
137 * \name gmtime
138 * \brief
139 * \param ptime Pointer to a variable of type time_t containing the time.
140 */
141 struct tm *
142 gmtime(const time_t * ptime)
143 {
144 __time64_t time64 = (__time64_t)*ptime;
145 return _gmtime64(&time64);
146 }