aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/timeutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/timeutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/timeutil.cpp385
1 files changed, 385 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/timeutil.cpp b/src/libs/dutil/WixToolset.DUtil/timeutil.cpp
new file mode 100644
index 00000000..b7953c94
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/timeutil.cpp
@@ -0,0 +1,385 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6// Exit macros
7#define TimeExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_TIMEUTIL, x, s, __VA_ARGS__)
8#define TimeExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_TIMEUTIL, x, s, __VA_ARGS__)
9#define TimeExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_TIMEUTIL, x, s, __VA_ARGS__)
10#define TimeExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_TIMEUTIL, x, s, __VA_ARGS__)
11#define TimeExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_TIMEUTIL, x, s, __VA_ARGS__)
12#define TimeExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_TIMEUTIL, x, s, __VA_ARGS__)
13#define TimeExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_TIMEUTIL, p, x, e, s, __VA_ARGS__)
14#define TimeExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_TIMEUTIL, p, x, s, __VA_ARGS__)
15#define TimeExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_TIMEUTIL, p, x, e, s, __VA_ARGS__)
16#define TimeExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_TIMEUTIL, p, x, s, __VA_ARGS__)
17#define TimeExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_TIMEUTIL, e, x, s, __VA_ARGS__)
18#define TimeExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_TIMEUTIL, g, x, s, __VA_ARGS__)
19
20const LPCWSTR DAY_OF_WEEK[] = { L"Sun", L"Mon", L"Tue", L"Wed", L"Thu", L"Fri", L"Sat" };
21const LPCWSTR MONTH_OF_YEAR[] = { L"None", L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec" };
22enum TIME_PARSER { DayOfWeek, DayOfMonth, MonthOfYear, Year, Hours, Minutes, Seconds, TimeZone };
23enum TIME_PARSERRFC3339 { RFC3339_Year, RFC3339_Month, RFC3339_Day, RFC3339_Hours, RFC3339_Minutes, RFC3339_Seconds, RFC3339_TimeZone };
24
25// prototypes
26static HRESULT DayFromString(
27 __in_z LPCWSTR wzDay,
28 __out WORD* pwDayOfWeek
29 );
30static HRESULT MonthFromString(
31 __in_z LPCWSTR wzMonth,
32 __out WORD* pwMonthOfYear
33 );
34
35
36/********************************************************************
37 TimeFromString - converts string to FILETIME
38
39*******************************************************************/
40extern "C" HRESULT DAPI TimeFromString(
41 __in_z LPCWSTR wzTime,
42 __out FILETIME* pFileTime
43 )
44{
45 Assert(wzTime && pFileTime);
46
47 HRESULT hr = S_OK;
48 LPWSTR pwzTime = NULL;
49
50 SYSTEMTIME sysTime = { };
51 TIME_PARSER timeParser = DayOfWeek;
52
53 LPCWSTR pwzStart = NULL;
54 LPWSTR pwzEnd = NULL;
55
56 hr = StrAllocString(&pwzTime, wzTime, 0);
57 TimeExitOnFailure(hr, "Failed to copy time.");
58
59 pwzStart = pwzEnd = pwzTime;
60 while (pwzEnd && *pwzEnd)
61 {
62 if (L',' == *pwzEnd || L' ' == *pwzEnd || L':' == *pwzEnd)
63 {
64 *pwzEnd = L'\0'; // null terminate
65 ++pwzEnd;
66
67 while (L' ' == *pwzEnd)
68 {
69 ++pwzEnd; // and skip past the blank space
70 }
71
72 switch (timeParser)
73 {
74 case DayOfWeek:
75 hr = DayFromString(pwzStart, &sysTime.wDayOfWeek);
76 TimeExitOnFailure(hr, "Failed to convert string to day: %ls", pwzStart);
77 break;
78
79 case DayOfMonth:
80 sysTime.wDay = (WORD)wcstoul(pwzStart, NULL, 10);
81 break;
82
83 case MonthOfYear:
84 hr = MonthFromString(pwzStart, &sysTime.wMonth);
85 TimeExitOnFailure(hr, "Failed to convert to month: %ls", pwzStart);
86 break;
87
88 case Year:
89 sysTime.wYear = (WORD)wcstoul(pwzStart, NULL, 10);
90 break;
91
92 case Hours:
93 sysTime.wHour = (WORD)wcstoul(pwzStart, NULL, 10);
94 break;
95
96 case Minutes:
97 sysTime.wMinute = (WORD)wcstoul(pwzStart, NULL, 10);
98 break;
99
100 case Seconds:
101 sysTime.wSecond = (WORD)wcstoul(pwzStart, NULL, 10);
102 break;
103
104 case TimeZone:
105 // TODO: do something with this in the future, but this should only hit outside of the while loop.
106 break;
107
108 default:
109 break;
110 }
111
112 pwzStart = pwzEnd;
113 timeParser = (TIME_PARSER)((int)timeParser + 1);
114 }
115
116 ++pwzEnd;
117 }
118
119
120 if (!::SystemTimeToFileTime(&sysTime, pFileTime))
121 {
122 TimeExitWithLastError(hr, "Failed to convert system time to file time.");
123 }
124
125LExit:
126 ReleaseStr(pwzTime);
127
128 return hr;
129}
130
131/********************************************************************
132 TimeFromString3339 - converts string formated in accorance with RFC3339 to FILETIME
133 http://tools.ietf.org/html/rfc3339
134*******************************************************************/
135extern "C" HRESULT DAPI TimeFromString3339(
136 __in_z LPCWSTR wzTime,
137 __out FILETIME* pFileTime
138 )
139{
140 Assert(wzTime && pFileTime);
141
142 HRESULT hr = S_OK;
143 LPWSTR pwzTime = NULL;
144
145 SYSTEMTIME sysTime = { };
146 TIME_PARSERRFC3339 timeParser = RFC3339_Year;
147
148 LPCWSTR pwzStart = NULL;
149 LPWSTR pwzEnd = NULL;
150
151 hr = StrAllocString(&pwzTime, wzTime, 0);
152 TimeExitOnFailure(hr, "Failed to copy time.");
153
154 pwzStart = pwzEnd = pwzTime;
155 while (pwzEnd && *pwzEnd)
156 {
157 if (L'T' == *pwzEnd || L':' == *pwzEnd || L'-' == *pwzEnd)
158 {
159 *pwzEnd = L'\0'; // null terminate
160 ++pwzEnd;
161
162 switch (timeParser)
163 {
164 case RFC3339_Year:
165 sysTime.wYear = (WORD)wcstoul(pwzStart, NULL, 10);
166 break;
167
168 case RFC3339_Month:
169 sysTime.wMonth = (WORD)wcstoul(pwzStart, NULL, 10);
170 break;
171
172 case RFC3339_Day:
173 sysTime.wDay = (WORD)wcstoul(pwzStart, NULL, 10);
174 break;
175
176 case RFC3339_Hours:
177 sysTime.wHour = (WORD)wcstoul(pwzStart, NULL, 10);
178 break;
179
180 case RFC3339_Minutes:
181 sysTime.wMinute = (WORD)wcstoul(pwzStart, NULL, 10);
182 break;
183
184 case RFC3339_Seconds:
185 sysTime.wSecond = (WORD)wcstoul(pwzStart, NULL, 10);
186 break;
187
188 case RFC3339_TimeZone:
189 // TODO: do something with this in the future, but this should only hit outside of the while loop.
190 break;
191
192 default:
193 break;
194 }
195
196 pwzStart = pwzEnd;
197 timeParser = (TIME_PARSERRFC3339)((int)timeParser + 1);
198 }
199
200 ++pwzEnd;
201 }
202
203
204 if (!::SystemTimeToFileTime(&sysTime, pFileTime))
205 {
206 TimeExitWithLastError(hr, "Failed to convert system time to file time.");
207 }
208
209LExit:
210 ReleaseStr(pwzTime);
211
212 return hr;
213}
214/****************************************************************************
215TimeCurrentTime - gets the current time in string format
216
217****************************************************************************/
218extern "C" HRESULT DAPI TimeCurrentTime(
219 __deref_out_z LPWSTR* ppwz,
220 __in BOOL fGMT
221 )
222{
223 SYSTEMTIME st;
224
225 if (fGMT)
226 {
227 ::GetSystemTime(&st);
228 }
229 else
230 {
231 SYSTEMTIME stGMT;
232 TIME_ZONE_INFORMATION tzi;
233
234 ::GetTimeZoneInformation(&tzi);
235 ::GetSystemTime(&stGMT);
236 ::SystemTimeToTzSpecificLocalTime(&tzi, &stGMT, &st);
237 }
238
239 return StrAllocFormatted(ppwz, L"%02d:%02d:%02d", st.wHour, st.wMinute, st.wSecond);
240}
241
242
243/****************************************************************************
244TimeCurrentDateTime - gets the current date and time in string format,
245 per format described in RFC 3339
246****************************************************************************/
247extern "C" HRESULT DAPI TimeCurrentDateTime(
248 __deref_out_z LPWSTR* ppwz,
249 __in BOOL fGMT
250 )
251{
252 SYSTEMTIME st;
253
254 ::GetSystemTime(&st);
255
256 return TimeSystemDateTime(ppwz, &st, fGMT);
257}
258
259
260/****************************************************************************
261TimeSystemDateTime - converts the provided system time struct to string format,
262 per format described in RFC 3339
263****************************************************************************/
264extern "C" HRESULT DAPI TimeSystemDateTime(
265 __deref_out_z LPWSTR* ppwz,
266 __in const SYSTEMTIME *pst,
267 __in BOOL fGMT
268 )
269{
270 DWORD dwAbsBias = 0;
271
272 if (fGMT)
273 {
274 return StrAllocFormatted(ppwz, L"%04hu-%02hu-%02huT%02hu:%02hu:%02huZ", pst->wYear, pst->wMonth, pst->wDay, pst->wHour, pst->wMinute, pst->wSecond);
275 }
276 else
277 {
278 SYSTEMTIME st;
279 TIME_ZONE_INFORMATION tzi;
280
281 ::GetTimeZoneInformation(&tzi);
282 ::SystemTimeToTzSpecificLocalTime(&tzi, pst, &st);
283 dwAbsBias = abs(tzi.Bias);
284
285 return StrAllocFormatted(ppwz, L"%04hu-%02hu-%02huT%02hu:%02hu:%02hu%c%02u:%02u", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, 0 >= tzi.Bias ? L'+' : L'-', dwAbsBias / 60, dwAbsBias % 60);
286 }
287}
288
289
290/****************************************************************************
291TimeSystemToDateTimeString - converts the provided system time struct to
292 string format representing date and time for the specified locale
293****************************************************************************/
294HRESULT DAPI TimeSystemToDateTimeString(
295 __deref_out_z LPWSTR* ppwz,
296 __in const SYSTEMTIME* pst,
297 __in LCID locale
298 )
299{
300 HRESULT hr = S_OK;
301 const WCHAR * DATE_FORMAT = L"MMM dd',' yyyy',' ";
302 const WCHAR * TIME_FORMAT = L"hh':'mm':'ss tt";
303 int iLenDate = 0;
304 int iLenTime = 0;
305
306 iLenDate = ::GetDateFormatW(locale, 0, pst, DATE_FORMAT, NULL, 0);
307 if (0 >= iLenDate)
308 {
309 TimeExitWithLastError(hr, "Failed to get date format with NULL");
310 }
311
312 iLenTime = ::GetTimeFormatW(locale, 0, pst, TIME_FORMAT, NULL, 0);
313 if (0 >= iLenTime)
314 {
315 TimeExitWithLastError(hr, "Failed to get time format with NULL");
316 }
317
318 // Between both lengths we account for 2 null terminators, and only need one, so we subtract one
319 hr = StrAlloc(ppwz, iLenDate + iLenTime - 1);
320 TimeExitOnFailure(hr, "Failed to allocate string");
321
322 if (!::GetDateFormatW(locale, 0, pst, DATE_FORMAT, *ppwz, iLenDate))
323 {
324 TimeExitWithLastError(hr, "Failed to get date format with buffer");
325 }
326 // Space to separate them
327 (*ppwz)[iLenDate - 1] = ' ';
328
329 if (!::GetTimeFormatW(locale, 0, pst, TIME_FORMAT, (*ppwz) + iLenDate - 1, iLenTime))
330 {
331 TimeExitWithLastError(hr, "Failed to get time format with buffer");
332 }
333
334LExit:
335 return hr;
336}
337
338/********************************************************************
339 DayFromString - converts string to day
340
341*******************************************************************/
342static HRESULT DayFromString(
343 __in_z LPCWSTR wzDay,
344 __out WORD* pwDayOfWeek
345 )
346{
347 HRESULT hr = E_INVALIDARG; // assume we won't find a matching name
348
349 for (WORD i = 0; i < countof(DAY_OF_WEEK); ++i)
350 {
351 if (0 == lstrcmpW(wzDay, DAY_OF_WEEK[i]))
352 {
353 *pwDayOfWeek = i;
354 hr = S_OK;
355 break;
356 }
357 }
358
359 return hr;
360}
361
362
363/********************************************************************
364 MonthFromString - converts string to month
365
366*******************************************************************/
367static HRESULT MonthFromString(
368 __in_z LPCWSTR wzMonth,
369 __out WORD* pwMonthOfYear
370 )
371{
372 HRESULT hr = E_INVALIDARG; // assume we won't find a matching name
373
374 for (WORD i = 0; i < countof(MONTH_OF_YEAR); ++i)
375 {
376 if (0 == lstrcmpW(wzMonth, MONTH_OF_YEAR[i]))
377 {
378 *pwMonthOfYear = i;
379 hr = S_OK;
380 break;
381 }
382 }
383
384 return hr;
385}