ReactOS 0.4.16-dev-852-gcfcc8d8
gmtime.cpp
Go to the documentation of this file.
1//
2// gmtime.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// The gmtime() family of functions, which converts a time_t value into a tm
7// structure in UTC.
8//
10
11
12
13// This is a utility that allows us to compute the year value differently for
14// 32-bit and 64-bit time_t objects.
15static int __cdecl compute_year(__time32_t& caltim, bool& is_leap_year) throw()
16{
17 // Determine years since 1970. First, identify the four-year interval
18 // since this makes handling leap-years easy (note that 2000 IS a
19 // leap year and 2100 is out-of-range).
20 int tmptim = static_cast<int>(caltim / _FOUR_YEAR_SEC);
21 caltim -= static_cast<__time32_t>(tmptim) * _FOUR_YEAR_SEC;
22
23 // Determine which year of the interval
24 tmptim = (tmptim * 4) + 70; // 1970, 1974, 1978,...,etc.
25
26 if (caltim >= _YEAR_SEC)
27 {
28 tmptim++; // 1971, 1975, 1979,...,etc.
29 caltim -= _YEAR_SEC;
30
31 if (caltim >= _YEAR_SEC)
32 {
33 tmptim++; // 1972, 1976, 1980,...,etc.
34 caltim -= _YEAR_SEC;
35
36 // Note, it takes 366 days-worth of seconds to get past a leap
37 // year.
38 if (caltim >= (_YEAR_SEC + _DAY_SEC))
39 {
40 tmptim++; // 1973, 1977, 1981,...,etc.
41 caltim -= (_YEAR_SEC + _DAY_SEC);
42 }
43 else
44 {
45 // In a leap year after all, set the flag.
46 is_leap_year = true;
47 }
48 }
49 }
50
51 return tmptim;
52}
53
54static int __cdecl compute_year(__time64_t& caltim, bool& is_leap_year) throw()
55{
56 // Determine the years since 1900. Start by ignoring leap years:
57 int tmptim = static_cast<int>(caltim / _YEAR_SEC) + 70;
58 caltim -= static_cast<__time64_t>(tmptim - 70) * _YEAR_SEC;
59
60 // Correct for elapsed leap years:
61 caltim -= static_cast<__time64_t>(__crt_time_elapsed_leap_years(tmptim)) * _DAY_SEC;
62
63 // If we have underflowed the __time64_t range (i.e., if caltim < 0),
64 // back up one year, adjusting the correction if necessary.
65 if (caltim < 0)
66 {
67 caltim += static_cast<__time64_t>(_YEAR_SEC);
68 tmptim--;
69 if (__crt_time_is_leap_year(tmptim))
70 {
71 caltim += _DAY_SEC;
72 is_leap_year = true;
73 }
74 }
75 else if (__crt_time_is_leap_year(tmptim))
76 {
77 is_leap_year = true;
78 }
79
80 return tmptim;
81}
82
83// Converts a time_t value into a tm structure in UTC. Stores the tm structure
84// into the '*ptm' buffer. Returns zero on success; returns an error code on
85// failure
86template <typename TimeType>
87static errno_t __cdecl common_gmtime_s(tm* const ptm, TimeType const* const timp) throw()
88{
89 typedef __crt_time_time_t_traits<__time64_t> time_traits;
90
91 _VALIDATE_RETURN_ERRCODE(ptm != nullptr, EINVAL)
92 memset(ptm, 0xff, sizeof(tm));
93
94 _VALIDATE_RETURN_ERRCODE(timp != nullptr, EINVAL);
95 TimeType caltim = *timp;
96
98
99 // Upper bound check only necessary for _gmtime64_s (it's > LONG_MAX).
100 // For _gmtime32_s, any positive number is within range (<= LONG_MAX).
101 _VALIDATE_RETURN_ERRCODE_NOEXC(caltim <= time_traits::max_time_t + _MAX_LOCAL_TIME, EINVAL)
102
103 // tmptim now holds the value for tm_year. caltim now holds the
104 // number of elapsed seconds since the beginning of that year.
105 bool is_leap_year = false;
106 ptm->tm_year = compute_year(caltim, is_leap_year);
107
108 // Determine days since January 1 (0 - 365). This is the tm_yday value.
109 // Leave caltim with number of elapsed seconds in that day.
110 ptm->tm_yday = static_cast<int>(caltim / _DAY_SEC);
111 caltim -= static_cast<TimeType>(ptm->tm_yday) * _DAY_SEC;
112
113 // Determine months since January (0 - 11) and day of month (1 - 31):
114 int const* const mdays = is_leap_year ? _lpdays : _days;
115
116 int tmptim = 0;
117 for (tmptim = 1 ; mdays[tmptim] < ptm->tm_yday ; tmptim++)
118 {
119 }
120
121 ptm->tm_mon = --tmptim;
122
123 ptm->tm_mday = ptm->tm_yday - mdays[tmptim];
124
125 // Determine days since Sunday (0 - 6)
126 ptm->tm_wday = (static_cast<int>(*timp / _DAY_SEC) + _BASE_DOW) % 7;
127
128 // Determine hours since midnight (0 - 23), minutes after the hour
129 // (0 - 59), and seconds after the minute (0 - 59).
130 ptm->tm_hour = static_cast<int>(caltim / 3600);
131 caltim -= static_cast<TimeType>(ptm->tm_hour) * 3600L;
132
133 ptm->tm_min = static_cast<int>(caltim / 60);
134 ptm->tm_sec = static_cast<int>(caltim - (ptm->tm_min) * 60);
135
136 ptm->tm_isdst = 0;
137 return 0;
138}
139
140extern "C" errno_t __cdecl _gmtime32_s(tm* const result, __time32_t const* const time_value)
141{
142 return common_gmtime_s(result, time_value);
143}
144
145extern "C" errno_t __cdecl _gmtime64_s(tm* const result, __time64_t const* const time_value)
146{
147 return common_gmtime_s(result, time_value);
148}
149
150
151
152// Gets the thread-local buffer to be used by gmtime. Returns a pointer to the
153// buffer on success; returns null and sets errno on failure.
155{
157 if (ptd == nullptr)
158 {
159 errno = ENOMEM;
160 return nullptr;
161 }
162
163 if (ptd->_gmtime_buffer != nullptr)
164 {
165 return ptd->_gmtime_buffer;
166 }
167
168 ptd->_gmtime_buffer = _malloc_crt_t(tm, 1).detach();
169 if (ptd->_gmtime_buffer == nullptr)
170 {
171 errno = ENOMEM;
172 return nullptr;
173 }
174
175 return ptd->_gmtime_buffer;
176}
177
178
179// Converts a time_t value into a tm structure in UTC. Returns a pointer to a
180// thread-local buffer containing the tm structure on success; returns null on
181// failure.
182template <typename TimeType>
183_Success_(return != 0)
184static tm* __cdecl common_gmtime(TimeType const* const time_value) throw()
185{
186 tm* const ptm = __getgmtimebuf();
187 if (ptm == nullptr)
188 return nullptr;
189
190 if (common_gmtime_s(ptm, time_value) != 0)
191 return nullptr;
192
193 return ptm;
194}
195
196extern "C" tm* __cdecl _gmtime32(__time32_t const* const time_value)
197{
198 return common_gmtime(time_value);
199}
200
201extern "C" tm* __cdecl _gmtime64(__time64_t const* const time_value)
202{
203 return common_gmtime(time_value);
204}
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
#define __cdecl
Definition: accygwin.h:79
__acrt_ptd *__cdecl __acrt_getptd_noexit(void)
#define _BASE_DOW
#define _DAY_SEC
int const _lpdays[]
Definition: days.cpp:21
bool __cdecl __crt_time_is_leap_year(TimeType const yr)
TimeType __cdecl __crt_time_elapsed_leap_years(TimeType const yr)
#define _FOUR_YEAR_SEC
#define _YEAR_SEC
int const _days[]
Definition: days.cpp:14
#define _MIN_LOCAL_TIME
#define _MAX_LOCAL_TIME
result_buffer_count char *const _In_ int const _In_ bool const _In_ unsigned const _In_ STRFLT const _In_ bool const _Inout_ __crt_cached_ptd_host &ptd throw()
Definition: cvt.cpp:119
_In_ size_t const _In_ int _In_ bool const _In_ unsigned const _In_ __acrt_rounding_mode const _Inout_ __crt_cached_ptd_host & ptd
Definition: cvt.cpp:355
GLuint64EXT * result
Definition: glext.h:11304
tm *__cdecl _gmtime32(__time32_t const *const time_value)
Definition: gmtime.cpp:196
errno_t __cdecl _gmtime32_s(tm *const result, __time32_t const *const time_value)
Definition: gmtime.cpp:140
static int __cdecl compute_year(__time32_t &caltim, bool &is_leap_year)
Definition: gmtime.cpp:15
tm *__cdecl _gmtime64(__time64_t const *const time_value)
Definition: gmtime.cpp:201
static errno_t __cdecl common_gmtime_s(tm *const ptm, TimeType const *const timp)
Definition: gmtime.cpp:87
tm *__cdecl __getgmtimebuf()
Definition: gmtime.cpp:154
errno_t __cdecl _gmtime64_s(tm *const result, __time64_t const *const time_value)
Definition: gmtime.cpp:145
#define _VALIDATE_RETURN_ERRCODE(expr, errorcode)
#define _VALIDATE_RETURN_ERRCODE_NOEXC(expr, errorcode)
#define _Success_(c)
Definition: no_sal2.h:84
#define errno
Definition: errno.h:18
long __time32_t
Definition: time.h:24
#define memset(x, y, z)
Definition: compat.h:39
Definition: time.h:68
__int64 __time64_t
Definition: corecrt.h:619
int errno_t
Definition: corecrt.h:615
#define const
Definition: zconf.h:233