VirtualBox

source: vbox/trunk/include/iprt/time.h@ 70942

Last change on this file since 70942 was 70895, checked in by vboxsync, 7 years ago

IPRT: Added RTTimeCompare and made use of it in the RTAsn1Time methods instead of the range limited RTTimeSpecCompare. Makes certificates with expire time beyond year 3000 found on windows 10 insider builds (??) work.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.7 KB
Line 
1/** @file
2 * IPRT - Time.
3 */
4
5/*
6 * Copyright (C) 2006-2017 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 *
16 * The contents of this file may alternatively be used under the terms
17 * of the Common Development and Distribution License Version 1.0
18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
19 * VirtualBox OSE distribution, in which case the provisions of the
20 * CDDL are applicable instead of those of the GPL.
21 *
22 * You may elect to license modified versions of this file under the
23 * terms and conditions of either the GPL or the CDDL or both.
24 */
25
26#ifndef ___iprt_time_h
27#define ___iprt_time_h
28
29#include <iprt/cdefs.h>
30#include <iprt/types.h>
31
32RT_C_DECLS_BEGIN
33
34/** @defgroup grp_rt_time RTTime - Time
35 * @ingroup grp_rt
36 * @{
37 */
38
39/** Time Specification.
40 *
41 * Use the inline RTTimeSpecGet/Set to operate on structure this so we
42 * can easily change the representation if required later.
43 *
44 * The current representation is in nanoseconds relative to the unix epoch
45 * (1970-01-01 00:00:00 UTC). This gives us an approximate span from
46 * 1678 to 2262 without sacrificing the resolution offered by the various
47 * host OSes (BSD & LINUX 1ns, NT 100ns).
48 */
49typedef struct RTTIMESPEC
50{
51 /** Nanoseconds since epoch.
52 * The name is intentially too long to be comfortable to use because you should be
53 * using inline helpers! */
54 int64_t i64NanosecondsRelativeToUnixEpoch;
55} RTTIMESPEC;
56
57
58/** @name RTTIMESPEC methods
59 * @{ */
60
61/**
62 * Gets the time as nanoseconds relative to the unix epoch.
63 *
64 * @returns Nanoseconds relative to unix epoch.
65 * @param pTime The time spec to interpret.
66 */
67DECLINLINE(int64_t) RTTimeSpecGetNano(PCRTTIMESPEC pTime)
68{
69 return pTime->i64NanosecondsRelativeToUnixEpoch;
70}
71
72
73/**
74 * Sets the time give by nanoseconds relative to the unix epoch.
75 *
76 * @returns pTime.
77 * @param pTime The time spec to modify.
78 * @param i64Nano The new time in nanoseconds.
79 */
80DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNano(PRTTIMESPEC pTime, int64_t i64Nano)
81{
82 pTime->i64NanosecondsRelativeToUnixEpoch = i64Nano;
83 return pTime;
84}
85
86
87/**
88 * Gets the time as microseconds relative to the unix epoch.
89 *
90 * @returns microseconds relative to unix epoch.
91 * @param pTime The time spec to interpret.
92 */
93DECLINLINE(int64_t) RTTimeSpecGetMicro(PCRTTIMESPEC pTime)
94{
95 return pTime->i64NanosecondsRelativeToUnixEpoch / RT_NS_1US;
96}
97
98
99/**
100 * Sets the time given by microseconds relative to the unix epoch.
101 *
102 * @returns pTime.
103 * @param pTime The time spec to modify.
104 * @param i64Micro The new time in microsecond.
105 */
106DECLINLINE(PRTTIMESPEC) RTTimeSpecSetMicro(PRTTIMESPEC pTime, int64_t i64Micro)
107{
108 pTime->i64NanosecondsRelativeToUnixEpoch = i64Micro * RT_NS_1US;
109 return pTime;
110}
111
112
113/**
114 * Gets the time as milliseconds relative to the unix epoch.
115 *
116 * @returns milliseconds relative to unix epoch.
117 * @param pTime The time spec to interpret.
118 */
119DECLINLINE(int64_t) RTTimeSpecGetMilli(PCRTTIMESPEC pTime)
120{
121 return pTime->i64NanosecondsRelativeToUnixEpoch / RT_NS_1MS;
122}
123
124
125/**
126 * Sets the time given by milliseconds relative to the unix epoch.
127 *
128 * @returns pTime.
129 * @param pTime The time spec to modify.
130 * @param i64Milli The new time in milliseconds.
131 */
132DECLINLINE(PRTTIMESPEC) RTTimeSpecSetMilli(PRTTIMESPEC pTime, int64_t i64Milli)
133{
134 pTime->i64NanosecondsRelativeToUnixEpoch = i64Milli * RT_NS_1MS;
135 return pTime;
136}
137
138
139/**
140 * Gets the time as seconds relative to the unix epoch.
141 *
142 * @returns seconds relative to unix epoch.
143 * @param pTime The time spec to interpret.
144 */
145DECLINLINE(int64_t) RTTimeSpecGetSeconds(PCRTTIMESPEC pTime)
146{
147 return pTime->i64NanosecondsRelativeToUnixEpoch / RT_NS_1SEC;
148}
149
150
151/**
152 * Sets the time given by seconds relative to the unix epoch.
153 *
154 * @returns pTime.
155 * @param pTime The time spec to modify.
156 * @param i64Seconds The new time in seconds.
157 */
158DECLINLINE(PRTTIMESPEC) RTTimeSpecSetSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
159{
160 pTime->i64NanosecondsRelativeToUnixEpoch = i64Seconds * RT_NS_1SEC;
161 return pTime;
162}
163
164
165/**
166 * Makes the time spec absolute like abs() does (i.e. a positive value).
167 *
168 * @returns pTime.
169 * @param pTime The time spec to modify.
170 */
171DECLINLINE(PRTTIMESPEC) RTTimeSpecAbsolute(PRTTIMESPEC pTime)
172{
173 if (pTime->i64NanosecondsRelativeToUnixEpoch < 0)
174 pTime->i64NanosecondsRelativeToUnixEpoch = -pTime->i64NanosecondsRelativeToUnixEpoch;
175 return pTime;
176}
177
178
179/**
180 * Negates the time.
181 *
182 * @returns pTime.
183 * @param pTime The time spec to modify.
184 */
185DECLINLINE(PRTTIMESPEC) RTTimeSpecNegate(PRTTIMESPEC pTime)
186{
187 pTime->i64NanosecondsRelativeToUnixEpoch = -pTime->i64NanosecondsRelativeToUnixEpoch;
188 return pTime;
189}
190
191
192/**
193 * Adds a time period to the time.
194 *
195 * @returns pTime.
196 * @param pTime The time spec to modify.
197 * @param pTimeAdd The time spec to add to pTime.
198 */
199DECLINLINE(PRTTIMESPEC) RTTimeSpecAdd(PRTTIMESPEC pTime, PCRTTIMESPEC pTimeAdd)
200{
201 pTime->i64NanosecondsRelativeToUnixEpoch += pTimeAdd->i64NanosecondsRelativeToUnixEpoch;
202 return pTime;
203}
204
205
206/**
207 * Adds a time period give as nanoseconds from the time.
208 *
209 * @returns pTime.
210 * @param pTime The time spec to modify.
211 * @param i64Nano The time period in nanoseconds.
212 */
213DECLINLINE(PRTTIMESPEC) RTTimeSpecAddNano(PRTTIMESPEC pTime, int64_t i64Nano)
214{
215 pTime->i64NanosecondsRelativeToUnixEpoch += i64Nano;
216 return pTime;
217}
218
219
220/**
221 * Adds a time period give as microseconds from the time.
222 *
223 * @returns pTime.
224 * @param pTime The time spec to modify.
225 * @param i64Micro The time period in microseconds.
226 */
227DECLINLINE(PRTTIMESPEC) RTTimeSpecAddMicro(PRTTIMESPEC pTime, int64_t i64Micro)
228{
229 pTime->i64NanosecondsRelativeToUnixEpoch += i64Micro * RT_NS_1US;
230 return pTime;
231}
232
233
234/**
235 * Adds a time period give as milliseconds from the time.
236 *
237 * @returns pTime.
238 * @param pTime The time spec to modify.
239 * @param i64Milli The time period in milliseconds.
240 */
241DECLINLINE(PRTTIMESPEC) RTTimeSpecAddMilli(PRTTIMESPEC pTime, int64_t i64Milli)
242{
243 pTime->i64NanosecondsRelativeToUnixEpoch += i64Milli * RT_NS_1MS;
244 return pTime;
245}
246
247
248/**
249 * Adds a time period give as seconds from the time.
250 *
251 * @returns pTime.
252 * @param pTime The time spec to modify.
253 * @param i64Seconds The time period in seconds.
254 */
255DECLINLINE(PRTTIMESPEC) RTTimeSpecAddSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
256{
257 pTime->i64NanosecondsRelativeToUnixEpoch += i64Seconds * RT_NS_1SEC;
258 return pTime;
259}
260
261
262/**
263 * Subtracts a time period from the time.
264 *
265 * @returns pTime.
266 * @param pTime The time spec to modify.
267 * @param pTimeSub The time spec to subtract from pTime.
268 */
269DECLINLINE(PRTTIMESPEC) RTTimeSpecSub(PRTTIMESPEC pTime, PCRTTIMESPEC pTimeSub)
270{
271 pTime->i64NanosecondsRelativeToUnixEpoch -= pTimeSub->i64NanosecondsRelativeToUnixEpoch;
272 return pTime;
273}
274
275
276/**
277 * Subtracts a time period give as nanoseconds from the time.
278 *
279 * @returns pTime.
280 * @param pTime The time spec to modify.
281 * @param i64Nano The time period in nanoseconds.
282 */
283DECLINLINE(PRTTIMESPEC) RTTimeSpecSubNano(PRTTIMESPEC pTime, int64_t i64Nano)
284{
285 pTime->i64NanosecondsRelativeToUnixEpoch -= i64Nano;
286 return pTime;
287}
288
289
290/**
291 * Subtracts a time period give as microseconds from the time.
292 *
293 * @returns pTime.
294 * @param pTime The time spec to modify.
295 * @param i64Micro The time period in microseconds.
296 */
297DECLINLINE(PRTTIMESPEC) RTTimeSpecSubMicro(PRTTIMESPEC pTime, int64_t i64Micro)
298{
299 pTime->i64NanosecondsRelativeToUnixEpoch -= i64Micro * RT_NS_1US;
300 return pTime;
301}
302
303
304/**
305 * Subtracts a time period give as milliseconds from the time.
306 *
307 * @returns pTime.
308 * @param pTime The time spec to modify.
309 * @param i64Milli The time period in milliseconds.
310 */
311DECLINLINE(PRTTIMESPEC) RTTimeSpecSubMilli(PRTTIMESPEC pTime, int64_t i64Milli)
312{
313 pTime->i64NanosecondsRelativeToUnixEpoch -= i64Milli * RT_NS_1MS;
314 return pTime;
315}
316
317
318/**
319 * Subtracts a time period give as seconds from the time.
320 *
321 * @returns pTime.
322 * @param pTime The time spec to modify.
323 * @param i64Seconds The time period in seconds.
324 */
325DECLINLINE(PRTTIMESPEC) RTTimeSpecSubSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
326{
327 pTime->i64NanosecondsRelativeToUnixEpoch -= i64Seconds * RT_NS_1SEC;
328 return pTime;
329}
330
331
332/**
333 * Gives the time in seconds and nanoseconds.
334 *
335 * @returns pTime.
336 * @param pTime The time spec to interpret.
337 * @param *pi32Seconds Where to store the time period in seconds.
338 * @param *pi32Nano Where to store the time period in nanoseconds.
339 */
340DECLINLINE(void) RTTimeSpecGetSecondsAndNano(PRTTIMESPEC pTime, int32_t *pi32Seconds, int32_t *pi32Nano)
341{
342 int64_t i64 = RTTimeSpecGetNano(pTime);
343 int32_t i32Nano = (int32_t)(i64 % RT_NS_1SEC);
344 i64 /= RT_NS_1SEC;
345 if (i32Nano < 0)
346 {
347 i32Nano += RT_NS_1SEC;
348 i64--;
349 }
350 *pi32Seconds = (int32_t)i64;
351 *pi32Nano = i32Nano;
352}
353
354
355/* PORTME: Add struct timeval guard macro here. */
356#if defined(RTTIME_INCL_TIMEVAL) || defined(_STRUCT_TIMEVAL) || defined(_SYS__TIMEVAL_H_) || defined(_SYS_TIME_H) || defined(_TIMEVAL) || defined(_LINUX_TIME_H) \
357 || (defined(RT_OS_NETBSD) && defined(_SYS_TIME_H_))
358/**
359 * Gets the time as POSIX timeval.
360 *
361 * @returns pTime.
362 * @param pTime The time spec to interpret.
363 * @param pTimeval Where to store the time as POSIX timeval.
364 */
365DECLINLINE(struct timeval *) RTTimeSpecGetTimeval(PCRTTIMESPEC pTime, struct timeval *pTimeval)
366{
367 int64_t i64 = RTTimeSpecGetMicro(pTime);
368 int32_t i32Micro = (int32_t)(i64 % RT_US_1SEC);
369 i64 /= RT_US_1SEC;
370 if (i32Micro < 0)
371 {
372 i32Micro += RT_US_1SEC;
373 i64--;
374 }
375 pTimeval->tv_sec = (time_t)i64;
376 pTimeval->tv_usec = i32Micro;
377 return pTimeval;
378}
379
380/**
381 * Sets the time as POSIX timeval.
382 *
383 * @returns pTime.
384 * @param pTime The time spec to modify.
385 * @param pTimeval Pointer to the POSIX timeval struct with the new time.
386 */
387DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimeval(PRTTIMESPEC pTime, const struct timeval *pTimeval)
388{
389 return RTTimeSpecAddMicro(RTTimeSpecSetSeconds(pTime, pTimeval->tv_sec), pTimeval->tv_usec);
390}
391#endif /* various ways of detecting struct timeval */
392
393
394/* PORTME: Add struct timespec guard macro here. */
395#if defined(RTTIME_INCL_TIMESPEC) || defined(_STRUCT_TIMESPEC) || defined(_SYS__TIMESPEC_H_) || defined(TIMEVAL_TO_TIMESPEC) || defined(_TIMESPEC) \
396 || (defined(RT_OS_NETBSD) && defined(_SYS_TIME_H_))
397/**
398 * Gets the time as POSIX timespec.
399 *
400 * @returns pTime.
401 * @param pTime The time spec to interpret.
402 * @param pTimespec Where to store the time as POSIX timespec.
403 */
404DECLINLINE(struct timespec *) RTTimeSpecGetTimespec(PCRTTIMESPEC pTime, struct timespec *pTimespec)
405{
406 int64_t i64 = RTTimeSpecGetNano(pTime);
407 int32_t i32Nano = (int32_t)(i64 % RT_NS_1SEC);
408 i64 /= RT_NS_1SEC;
409 if (i32Nano < 0)
410 {
411 i32Nano += RT_NS_1SEC;
412 i64--;
413 }
414 pTimespec->tv_sec = (time_t)i64;
415 pTimespec->tv_nsec = i32Nano;
416 return pTimespec;
417}
418
419/**
420 * Sets the time as POSIX timespec.
421 *
422 * @returns pTime.
423 * @param pTime The time spec to modify.
424 * @param pTimespec Pointer to the POSIX timespec struct with the new time.
425 */
426DECLINLINE(PRTTIMESPEC) RTTimeSpecSetTimespec(PRTTIMESPEC pTime, const struct timespec *pTimespec)
427{
428 return RTTimeSpecAddNano(RTTimeSpecSetSeconds(pTime, pTimespec->tv_sec), pTimespec->tv_nsec);
429}
430#endif /* various ways of detecting struct timespec */
431
432
433
434/** The offset of the unix epoch and the base for NT time (in 100ns units).
435 * Nt time starts at 1601-01-01 00:00:00. */
436#define RTTIME_NT_TIME_OFFSET_UNIX (116444736000000000LL)
437
438
439/**
440 * Gets the time as NT time.
441 *
442 * @returns Nt time.
443 * @param pTime The time spec to interpret.
444 */
445DECLINLINE(uint64_t) RTTimeSpecGetNtTime(PCRTTIMESPEC pTime)
446{
447 return pTime->i64NanosecondsRelativeToUnixEpoch / 100
448 + RTTIME_NT_TIME_OFFSET_UNIX;
449}
450
451
452/**
453 * Sets the time given by Nt time.
454 *
455 * @returns pTime.
456 * @param pTime The time spec to modify.
457 * @param u64NtTime The new time in Nt time.
458 */
459DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNtTime(PRTTIMESPEC pTime, uint64_t u64NtTime)
460{
461 pTime->i64NanosecondsRelativeToUnixEpoch =
462 ((int64_t)u64NtTime - RTTIME_NT_TIME_OFFSET_UNIX) * 100;
463 return pTime;
464}
465
466
467#ifdef _FILETIME_
468/**
469 * Gets the time as NT file time.
470 *
471 * @returns pFileTime.
472 * @param pTime The time spec to interpret.
473 * @param pFileTime Pointer to NT filetime structure.
474 */
475DECLINLINE(PFILETIME) RTTimeSpecGetNtFileTime(PCRTTIMESPEC pTime, PFILETIME pFileTime)
476{
477 *((uint64_t *)pFileTime) = RTTimeSpecGetNtTime(pTime);
478 return pFileTime;
479}
480
481/**
482 * Sets the time as NT file time.
483 *
484 * @returns pTime.
485 * @param pTime The time spec to modify.
486 * @param pFileTime Where to store the time as Nt file time.
487 */
488DECLINLINE(PRTTIMESPEC) RTTimeSpecSetNtFileTime(PRTTIMESPEC pTime, const FILETIME *pFileTime)
489{
490 return RTTimeSpecSetNtTime(pTime, *(const uint64_t *)pFileTime);
491}
492#endif
493
494
495/** The offset to the start of DOS time.
496 * DOS time starts 1980-01-01 00:00:00. */
497#define RTTIME_OFFSET_DOS_TIME (315532800000000000LL)
498
499
500/**
501 * Gets the time as seconds relative to the start of dos time.
502 *
503 * @returns seconds relative to the start of dos time.
504 * @param pTime The time spec to interpret.
505 */
506DECLINLINE(int64_t) RTTimeSpecGetDosSeconds(PCRTTIMESPEC pTime)
507{
508 return (pTime->i64NanosecondsRelativeToUnixEpoch - RTTIME_OFFSET_DOS_TIME)
509 / RT_NS_1SEC;
510}
511
512
513/**
514 * Sets the time given by seconds relative to the start of dos time.
515 *
516 * @returns pTime.
517 * @param pTime The time spec to modify.
518 * @param i64Seconds The new time in seconds relative to the start of dos time.
519 */
520DECLINLINE(PRTTIMESPEC) RTTimeSpecSetDosSeconds(PRTTIMESPEC pTime, int64_t i64Seconds)
521{
522 pTime->i64NanosecondsRelativeToUnixEpoch = i64Seconds * RT_NS_1SEC
523 + RTTIME_OFFSET_DOS_TIME;
524 return pTime;
525}
526
527
528/**
529 * Compare two time specs.
530 *
531 * @returns true they are equal.
532 * @returns false they are not equal.
533 * @param pTime1 The 1st time spec.
534 * @param pTime2 The 2nd time spec.
535 */
536DECLINLINE(bool) RTTimeSpecIsEqual(PCRTTIMESPEC pTime1, PCRTTIMESPEC pTime2)
537{
538 return pTime1->i64NanosecondsRelativeToUnixEpoch == pTime2->i64NanosecondsRelativeToUnixEpoch;
539}
540
541
542/**
543 * Compare two time specs.
544 *
545 * @returns 0 if equal, -1 if @a pLeft is smaller, 1 if @a pLeft is larger.
546 * @returns false they are not equal.
547 * @param pLeft The 1st time spec.
548 * @param pRight The 2nd time spec.
549 */
550DECLINLINE(int) RTTimeSpecCompare(PCRTTIMESPEC pLeft, PCRTTIMESPEC pRight)
551{
552 if (pLeft->i64NanosecondsRelativeToUnixEpoch == pRight->i64NanosecondsRelativeToUnixEpoch)
553 return 0;
554 return pLeft->i64NanosecondsRelativeToUnixEpoch < pRight->i64NanosecondsRelativeToUnixEpoch ? -1 : 1;
555}
556
557
558/**
559 * Converts a time spec to a ISO date string.
560 *
561 * @returns psz on success.
562 * @returns NULL on buffer underflow.
563 * @param pTime The time spec.
564 * @param psz Where to store the string.
565 * @param cb The size of the buffer.
566 */
567RTDECL(char *) RTTimeSpecToString(PCRTTIMESPEC pTime, char *psz, size_t cb);
568
569/**
570 * Attempts to convert an ISO date string to a time structure.
571 *
572 * We're a little forgiving with zero padding, unspecified parts, and leading
573 * and trailing spaces.
574 *
575 * @retval pTime on success,
576 * @retval NULL on failure.
577 * @param pTime The time spec.
578 * @param pszString The ISO date string to convert.
579 */
580RTDECL(PRTTIMESPEC) RTTimeSpecFromString(PRTTIMESPEC pTime, const char *pszString);
581
582/** @} */
583
584
585/**
586 * Exploded time.
587 */
588#pragma pack(1)
589typedef struct RTTIME
590{
591 /** The year number. */
592 int32_t i32Year;
593 /** The month of the year (1-12). January is 1. */
594 uint8_t u8Month;
595 /** The day of the week (0-6). Monday is 0. */
596 uint8_t u8WeekDay;
597 /** The day of the year (1-366). January the 1st is 1. */
598 uint16_t u16YearDay;
599 /** The day of the month (1-31). */
600 uint8_t u8MonthDay;
601 /** Hour of the day (0-23). */
602 uint8_t u8Hour;
603 /** The minute of the hour (0-59). */
604 uint8_t u8Minute;
605 /** The second of the minute (0-60).
606 * (u32Nanosecond / 1000000) */
607 uint8_t u8Second;
608 /** The nanoseconds of the second (0-999999999). */
609 uint32_t u32Nanosecond;
610 /** Flags, of the RTTIME_FLAGS_* \#defines. */
611 uint32_t fFlags;
612 /** UCT time offset in minutes (-840-840).
613 * @remarks The implementation of RTTimeLocal* isn't quite there yet, so this might not be 100% correct. */
614 int32_t offUTC;
615} RTTIME;
616#pragma pack()
617/** Pointer to a exploded time structure. */
618typedef RTTIME *PRTTIME;
619/** Pointer to a const exploded time structure. */
620typedef const RTTIME *PCRTTIME;
621
622/** @name RTTIME::fFlags values.
623 * @{ */
624/** Set if the time is UTC. If clear the time local time. */
625#define RTTIME_FLAGS_TYPE_MASK 3
626/** the time is UTC time. */
627#define RTTIME_FLAGS_TYPE_UTC 2
628/** The time is local time. */
629#define RTTIME_FLAGS_TYPE_LOCAL 3
630
631/** Set if the time is local and daylight saving time is in effect.
632 * Not bit is not valid if RTTIME_FLAGS_NO_DST_DATA is set. */
633#define RTTIME_FLAGS_DST RT_BIT(4)
634/** Set if the time is local and there is no data available on daylight saving time. */
635#define RTTIME_FLAGS_NO_DST_DATA RT_BIT(5)
636/** Set if the year is a leap year.
637 * This is mutual exclusiv with RTTIME_FLAGS_COMMON_YEAR. */
638#define RTTIME_FLAGS_LEAP_YEAR RT_BIT(6)
639/** Set if the year is a common year.
640 * This is mutual exclusiv with RTTIME_FLAGS_LEAP_YEAR. */
641#define RTTIME_FLAGS_COMMON_YEAR RT_BIT(7)
642/** The mask of valid flags. */
643#define RTTIME_FLAGS_MASK UINT32_C(0xff)
644/** @} */
645
646
647/**
648 * Gets the current system time (UTC).
649 *
650 * @returns pTime.
651 * @param pTime Where to store the time.
652 */
653RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime);
654
655/**
656 * Sets the system time.
657 *
658 * @returns IPRT status code
659 * @param pTime The new system time (UTC).
660 *
661 * @remarks This will usually fail because changing the wall time is usually
662 * requires extra privileges.
663 */
664RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime);
665
666/**
667 * Explodes a time spec (UTC).
668 *
669 * @returns pTime.
670 * @param pTime Where to store the exploded time.
671 * @param pTimeSpec The time spec to exploded.
672 */
673RTDECL(PRTTIME) RTTimeExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec);
674
675/**
676 * Implodes exploded time to a time spec (UTC).
677 *
678 * @returns pTime on success.
679 * @returns NULL if the pTime data is invalid.
680 * @param pTimeSpec Where to store the imploded UTC time.
681 * If pTime specifies a time which outside the range, maximum or
682 * minimum values will be returned.
683 * @param pTime Pointer to the exploded time to implode.
684 * The fields u8Month, u8WeekDay and u8MonthDay are not used,
685 * and all the other fields are expected to be within their
686 * bounds. Use RTTimeNormalize() to calculate u16YearDay and
687 * normalize the ranges of the fields.
688 */
689RTDECL(PRTTIMESPEC) RTTimeImplode(PRTTIMESPEC pTimeSpec, PCRTTIME pTime);
690
691/**
692 * Normalizes the fields of a time structure.
693 *
694 * It is possible to calculate year-day from month/day and vice
695 * versa. If you adjust any of of these, make sure to zero the
696 * other so you make it clear which of the fields to use. If
697 * it's ambiguous, the year-day field is used (and you get
698 * assertions in debug builds).
699 *
700 * All the time fields and the year-day or month/day fields will
701 * be adjusted for overflows. (Since all fields are unsigned, there
702 * is no underflows.) It is possible to exploit this for simple
703 * date math, though the recommended way of doing that to implode
704 * the time into a timespec and do the math on that.
705 *
706 * @returns pTime on success.
707 * @returns NULL if the data is invalid.
708 *
709 * @param pTime The time structure to normalize.
710 *
711 * @remarks This function doesn't work with local time, only with UTC time.
712 */
713RTDECL(PRTTIME) RTTimeNormalize(PRTTIME pTime);
714
715/**
716 * Gets the current local system time.
717 *
718 * @returns pTime.
719 * @param pTime Where to store the local time.
720 */
721RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime);
722
723/**
724 * Gets the delta between UTC and local time.
725 *
726 * @code
727 * RTTIMESPEC LocalTime;
728 * RTTimeSpecAddNano(RTTimeNow(&LocalTime), RTTimeLocalDeltaNano());
729 * @endcode
730 *
731 * @returns Returns the nanosecond delta between UTC and local time.
732 */
733RTDECL(int64_t) RTTimeLocalDeltaNano(void);
734
735/**
736 * Explodes a time spec to the localized timezone.
737 *
738 * @returns pTime.
739 * @param pTime Where to store the exploded time.
740 * @param pTimeSpec The time spec to exploded (UTC).
741 */
742RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec);
743
744/**
745 * Normalizes the fields of a time structure containing local time.
746 *
747 * See RTTimeNormalize for details.
748 *
749 * @returns pTime on success.
750 * @returns NULL if the data is invalid.
751 * @param pTime The time structure to normalize.
752 */
753RTDECL(PRTTIME) RTTimeLocalNormalize(PRTTIME pTime);
754
755/**
756 * Converts a time spec to a ISO date string.
757 *
758 * @returns psz on success.
759 * @returns NULL on buffer underflow.
760 * @param pTime The time. Caller should've normalized this.
761 * @param psz Where to store the string.
762 * @param cb The size of the buffer.
763 */
764RTDECL(char *) RTTimeToString(PCRTTIME pTime, char *psz, size_t cb);
765
766/**
767 * Attempts to convert an ISO date string to a time structure.
768 *
769 * We're a little forgiving with zero padding, unspecified parts, and leading
770 * and trailing spaces.
771 *
772 * @retval pTime on success,
773 * @retval NULL on failure.
774 * @param pTime Where to store the time on success.
775 * @param pszString The ISO date string to convert.
776 */
777RTDECL(PRTTIME) RTTimeFromString(PRTTIME pTime, const char *pszString);
778
779/**
780 * Checks if a year is a leap year or not.
781 *
782 * @returns true if it's a leap year.
783 * @returns false if it's a common year.
784 * @param i32Year The year in question.
785 */
786RTDECL(bool) RTTimeIsLeapYear(int32_t i32Year);
787
788/**
789 * Compares two normalized time structures.
790 *
791 * @retval 0 if equal.
792 * @retval -1 if @a pLeft is earlier than @a pRight.
793 * @retval 1 if @a pRight is earlier than @a pLeft.
794 *
795 * @param pLeft The left side time. NULL is accepted.
796 * @param pRight The right side time. NULL is accepted.
797 *
798 * @note A NULL time is considered smaller than anything else. If both are
799 * NULL, they are considered equal.
800 */
801RTDECL(int) RTTimeCompare(PCRTTIME pLeft, PCRTTIME pRight);
802
803/**
804 * Gets the current nanosecond timestamp.
805 *
806 * @returns nanosecond timestamp.
807 */
808RTDECL(uint64_t) RTTimeNanoTS(void);
809
810/**
811 * Gets the current millisecond timestamp.
812 *
813 * @returns millisecond timestamp.
814 */
815RTDECL(uint64_t) RTTimeMilliTS(void);
816
817/**
818 * Debugging the time api.
819 *
820 * @returns the number of 1ns steps which has been applied by RTTimeNanoTS().
821 */
822RTDECL(uint32_t) RTTimeDbgSteps(void);
823
824/**
825 * Debugging the time api.
826 *
827 * @returns the number of times the TSC interval expired RTTimeNanoTS().
828 */
829RTDECL(uint32_t) RTTimeDbgExpired(void);
830
831/**
832 * Debugging the time api.
833 *
834 * @returns the number of bad previous values encountered by RTTimeNanoTS().
835 */
836RTDECL(uint32_t) RTTimeDbgBad(void);
837
838/**
839 * Debugging the time api.
840 *
841 * @returns the number of update races in RTTimeNanoTS().
842 */
843RTDECL(uint32_t) RTTimeDbgRaces(void);
844
845/** @name RTTimeNanoTS GIP worker functions, for TM.
846 * @{ */
847/** Pointer to a RTTIMENANOTSDATA structure. */
848typedef struct RTTIMENANOTSDATA *PRTTIMENANOTSDATA;
849
850/**
851 * Nanosecond timestamp data.
852 *
853 * This is used to keep track of statistics and callback so IPRT
854 * and TM (VirtualBox) can share code.
855 *
856 * @remark Keep this in sync with the assembly version in timesupA.asm.
857 */
858typedef struct RTTIMENANOTSDATA
859{
860 /** Where the previous timestamp is stored.
861 * This is maintained to ensure that time doesn't go backwards or anything. */
862 uint64_t volatile *pu64Prev;
863
864 /**
865 * Helper function that's used by the assembly routines when something goes bust.
866 *
867 * @param pData Pointer to this structure.
868 * @param u64NanoTS The calculated nano ts.
869 * @param u64DeltaPrev The delta relative to the previously returned timestamp.
870 * @param u64PrevNanoTS The previously returned timestamp (as it was read it).
871 */
872 DECLCALLBACKMEMBER(void, pfnBad)(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS);
873
874 /**
875 * Callback for when rediscovery is required.
876 *
877 * @returns Nanosecond timestamp.
878 * @param pData Pointer to this structure.
879 */
880 DECLCALLBACKMEMBER(uint64_t, pfnRediscover)(PRTTIMENANOTSDATA pData);
881
882 /**
883 * Callback for when some CPU index related stuff goes wrong.
884 *
885 * @returns Nanosecond timestamp.
886 * @param pData Pointer to this structure.
887 * @param idApic The APIC ID if available, otherwise (UINT16_MAX-1).
888 * @param iCpuSet The CPU set index if available, otherwise
889 * (UINT16_MAX-1).
890 * @param iGipCpu The GIP CPU array index if available, otherwise
891 * (UINT16_MAX-1).
892 */
893 DECLCALLBACKMEMBER(uint64_t, pfnBadCpuIndex)(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
894
895 /** Number of 1ns steps because of overshooting the period. */
896 uint32_t c1nsSteps;
897 /** The number of times the interval expired (overflow). */
898 uint32_t cExpired;
899 /** Number of "bad" previous values. */
900 uint32_t cBadPrev;
901 /** The number of update races. */
902 uint32_t cUpdateRaces;
903} RTTIMENANOTSDATA;
904
905#ifndef IN_RING3
906/**
907 * The Ring-3 layout of the RTTIMENANOTSDATA structure.
908 */
909typedef struct RTTIMENANOTSDATAR3
910{
911 R3PTRTYPE(uint64_t volatile *) pu64Prev;
912 DECLR3CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
913 DECLR3CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
914 DECLR3CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
915 uint32_t c1nsSteps;
916 uint32_t cExpired;
917 uint32_t cBadPrev;
918 uint32_t cUpdateRaces;
919} RTTIMENANOTSDATAR3;
920#else
921typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR3;
922#endif
923
924#ifndef IN_RING0
925/**
926 * The Ring-3 layout of the RTTIMENANOTSDATA structure.
927 */
928typedef struct RTTIMENANOTSDATAR0
929{
930 R0PTRTYPE(uint64_t volatile *) pu64Prev;
931 DECLR0CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
932 DECLR0CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
933 DECLR0CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
934 uint32_t c1nsSteps;
935 uint32_t cExpired;
936 uint32_t cBadPrev;
937 uint32_t cUpdateRaces;
938} RTTIMENANOTSDATAR0;
939#else
940typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR0;
941#endif
942
943#ifndef IN_RC
944/**
945 * The RC layout of the RTTIMENANOTSDATA structure.
946 */
947typedef struct RTTIMENANOTSDATARC
948{
949 RCPTRTYPE(uint64_t volatile *) pu64Prev;
950 DECLRCCALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
951 DECLRCCALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
952 DECLRCCALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
953 uint32_t c1nsSteps;
954 uint32_t cExpired;
955 uint32_t cBadPrev;
956 uint32_t cUpdateRaces;
957} RTTIMENANOTSDATARC;
958#else
959typedef RTTIMENANOTSDATA RTTIMENANOTSDATARC;
960#endif
961
962/** Internal RTTimeNanoTS worker (assembly). */
963typedef DECLCALLBACK(uint64_t) FNTIMENANOTSINTERNAL(PRTTIMENANOTSDATA pData);
964/** Pointer to an internal RTTimeNanoTS worker (assembly). */
965typedef FNTIMENANOTSINTERNAL *PFNTIMENANOTSINTERNAL;
966RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarNoDelta(PRTTIMENANOTSDATA pData);
967RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarNoDelta(PRTTIMENANOTSDATA pData);
968#ifdef IN_RING3
969RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicId(PRTTIMENANOTSDATA pData);
970RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
971RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
972RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
973RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
974RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
975RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
976RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicId(PRTTIMENANOTSDATA pData);
977RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
978RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
979RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
980RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
981RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
982RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
983#else
984RTDECL(uint64_t) RTTimeNanoTSLegacyAsync(PRTTIMENANOTSDATA pData);
985RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDelta(PRTTIMENANOTSDATA pData);
986RTDECL(uint64_t) RTTimeNanoTSLFenceAsync(PRTTIMENANOTSDATA pData);
987RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDelta(PRTTIMENANOTSDATA pData);
988#endif
989
990/** @} */
991
992
993/**
994 * Gets the current nanosecond timestamp.
995 *
996 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
997 * resolution or performance optimizations.
998 *
999 * @returns nanosecond timestamp.
1000 */
1001RTDECL(uint64_t) RTTimeSystemNanoTS(void);
1002
1003/**
1004 * Gets the current millisecond timestamp.
1005 *
1006 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
1007 * resolution or performance optimizations.
1008 *
1009 * @returns millisecond timestamp.
1010 */
1011RTDECL(uint64_t) RTTimeSystemMilliTS(void);
1012
1013/**
1014 * Get the nanosecond timestamp relative to program startup.
1015 *
1016 * @returns Timestamp relative to program startup.
1017 */
1018RTDECL(uint64_t) RTTimeProgramNanoTS(void);
1019
1020/**
1021 * Get the microsecond timestamp relative to program startup.
1022 *
1023 * @returns Timestamp relative to program startup.
1024 */
1025RTDECL(uint64_t) RTTimeProgramMicroTS(void);
1026
1027/**
1028 * Get the millisecond timestamp relative to program startup.
1029 *
1030 * @returns Timestamp relative to program startup.
1031 */
1032RTDECL(uint64_t) RTTimeProgramMilliTS(void);
1033
1034/**
1035 * Get the second timestamp relative to program startup.
1036 *
1037 * @returns Timestamp relative to program startup.
1038 */
1039RTDECL(uint32_t) RTTimeProgramSecTS(void);
1040
1041/**
1042 * Get the RTTimeNanoTS() of when the program started.
1043 *
1044 * @returns Program startup timestamp.
1045 */
1046RTDECL(uint64_t) RTTimeProgramStartNanoTS(void);
1047
1048
1049/**
1050 * Time zone information.
1051 */
1052typedef struct RTTIMEZONEINFO
1053{
1054 /** Unix time zone name (continent/country[/city]|). */
1055 const char *pszUnixName;
1056 /** Windows time zone name. */
1057 const char *pszWindowsName;
1058 /** The length of the unix time zone name. */
1059 uint8_t cchUnixName;
1060 /** The length of the windows time zone name. */
1061 uint8_t cchWindowsName;
1062 /** Two letter country/territory code if applicable, otherwise 'ZZ'. */
1063 char szCountry[3];
1064 /** Two letter windows country/territory code if applicable.
1065 * Empty string if no windows mapping. */
1066 char szWindowsCountry[3];
1067#if 0 /* Add when needed and it's been extracted. */
1068 /** The standard delta in minutes (add to UTC). */
1069 int16_t cMinStdDelta;
1070 /** The daylight saving time delta in minutes (add to UTC). */
1071 int16_t cMinDstDelta;
1072#endif
1073 /** closest matching windows time zone index. */
1074 uint32_t idxWindows;
1075 /** Flags, RTTIMEZONEINFO_F_XXX. */
1076 uint32_t fFlags;
1077} RTTIMEZONEINFO;
1078/** Pointer to time zone info. */
1079typedef RTTIMEZONEINFO const *PCRTTIMEZONEINFO;
1080
1081/** @name RTTIMEZONEINFO_F_XXX - time zone info flags.
1082 * @{ */
1083/** Indicates golden mapping entry for a windows time zone name. */
1084#define RTTIMEZONEINFO_F_GOLDEN RT_BIT_32(0)
1085/** @} */
1086
1087/**
1088 * Looks up static time zone information by unix name.
1089 *
1090 * @returns Pointer to info entry if found, NULL if not.
1091 * @param pszName The unix zone name (TZ).
1092 */
1093RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByUnixName(const char *pszName);
1094
1095/**
1096 * Looks up static time zone information by window name.
1097 *
1098 * @returns Pointer to info entry if found, NULL if not.
1099 * @param pszName The windows zone name (reg key).
1100 */
1101RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByWindowsName(const char *pszName);
1102
1103/**
1104 * Looks up static time zone information by windows index.
1105 *
1106 * @returns Pointer to info entry if found, NULL if not.
1107 * @param idxZone The windows timezone index.
1108 */
1109RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByWindowsIndex(uint32_t idxZone);
1110
1111/**
1112 * Get the current time zone (TZ).
1113 *
1114 * @returns IPRT status code.
1115 * @param pszName Where to return the time zone name.
1116 * @param cbName The size of the name buffer.
1117 */
1118RTDECL(int) RTTimeZoneGetCurrent(char *pszName, size_t cbName);
1119
1120/** @} */
1121
1122RT_C_DECLS_END
1123
1124#endif
1125
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette