VirtualBox

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

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

IPRT/time: misc fixes (incorrect offUTC conversion sign, forgotten storing of offUTC, incorrect month/day calculation for first day of month, avoiding assertions when leap year needs to be recalulated) for local time, make RTTimeImplode process local time correctly, plus an implementation of RTTimeLocalNormalize and RTTimeConvertToZulu. Much improved testcase exercising overflow handling in the local time case.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 33.9 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 int32_t offUTC;
614} RTTIME;
615#pragma pack()
616/** Pointer to a exploded time structure. */
617typedef RTTIME *PRTTIME;
618/** Pointer to a const exploded time structure. */
619typedef const RTTIME *PCRTTIME;
620
621/** @name RTTIME::fFlags values.
622 * @{ */
623/** Set if the time is UTC. If clear the time local time. */
624#define RTTIME_FLAGS_TYPE_MASK 3
625/** the time is UTC time. */
626#define RTTIME_FLAGS_TYPE_UTC 2
627/** The time is local time. */
628#define RTTIME_FLAGS_TYPE_LOCAL 3
629
630/** Set if the time is local and daylight saving time is in effect.
631 * Not bit is not valid if RTTIME_FLAGS_NO_DST_DATA is set. */
632#define RTTIME_FLAGS_DST RT_BIT(4)
633/** Set if the time is local and there is no data available on daylight saving time. */
634#define RTTIME_FLAGS_NO_DST_DATA RT_BIT(5)
635/** Set if the year is a leap year.
636 * This is mutual exclusiv with RTTIME_FLAGS_COMMON_YEAR. */
637#define RTTIME_FLAGS_LEAP_YEAR RT_BIT(6)
638/** Set if the year is a common year.
639 * This is mutual exclusiv with RTTIME_FLAGS_LEAP_YEAR. */
640#define RTTIME_FLAGS_COMMON_YEAR RT_BIT(7)
641/** The mask of valid flags. */
642#define RTTIME_FLAGS_MASK UINT32_C(0xff)
643/** @} */
644
645
646/**
647 * Gets the current system time (UTC).
648 *
649 * @returns pTime.
650 * @param pTime Where to store the time.
651 */
652RTDECL(PRTTIMESPEC) RTTimeNow(PRTTIMESPEC pTime);
653
654/**
655 * Sets the system time.
656 *
657 * @returns IPRT status code
658 * @param pTime The new system time (UTC).
659 *
660 * @remarks This will usually fail because changing the wall time is usually
661 * requires extra privileges.
662 */
663RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime);
664
665/**
666 * Explodes a time spec (UTC).
667 *
668 * @returns pTime.
669 * @param pTime Where to store the exploded time.
670 * @param pTimeSpec The time spec to exploded.
671 */
672RTDECL(PRTTIME) RTTimeExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec);
673
674/**
675 * Implodes exploded time to a time spec (UTC).
676 *
677 * @returns pTime on success.
678 * @returns NULL if the pTime data is invalid.
679 * @param pTimeSpec Where to store the imploded UTC time.
680 * If pTime specifies a time which outside the range, maximum or
681 * minimum values will be returned.
682 * @param pTime Pointer to the exploded time to implode.
683 * The fields u8Month, u8WeekDay and u8MonthDay are not used,
684 * and all the other fields are expected to be within their
685 * bounds. Use RTTimeNormalize() to calculate u16YearDay and
686 * normalize the ranges of the fields.
687 */
688RTDECL(PRTTIMESPEC) RTTimeImplode(PRTTIMESPEC pTimeSpec, PCRTTIME pTime);
689
690/**
691 * Normalizes the fields of a time structure.
692 *
693 * It is possible to calculate year-day from month/day and vice
694 * versa. If you adjust any of of these, make sure to zero the
695 * other so you make it clear which of the fields to use. If
696 * it's ambiguous, the year-day field is used (and you get
697 * assertions in debug builds).
698 *
699 * All the time fields and the year-day or month/day fields will
700 * be adjusted for overflows. (Since all fields are unsigned, there
701 * is no underflows.) It is possible to exploit this for simple
702 * date math, though the recommended way of doing that to implode
703 * the time into a timespec and do the math on that.
704 *
705 * @returns pTime on success.
706 * @returns NULL if the data is invalid.
707 *
708 * @param pTime The time structure to normalize.
709 *
710 * @remarks This function doesn't work with local time, only with UTC time.
711 */
712RTDECL(PRTTIME) RTTimeNormalize(PRTTIME pTime);
713
714/**
715 * Gets the current local system time.
716 *
717 * @returns pTime.
718 * @param pTime Where to store the local time.
719 */
720RTDECL(PRTTIMESPEC) RTTimeLocalNow(PRTTIMESPEC pTime);
721
722/**
723 * Gets the delta between UTC and local time.
724 *
725 * @code
726 * RTTIMESPEC LocalTime;
727 * RTTimeSpecAddNano(RTTimeNow(&LocalTime), RTTimeLocalDeltaNano());
728 * @endcode
729 *
730 * @returns Returns the nanosecond delta between UTC and local time.
731 */
732RTDECL(int64_t) RTTimeLocalDeltaNano(void);
733
734/**
735 * Explodes a time spec to the localized timezone.
736 *
737 * @returns pTime.
738 * @param pTime Where to store the exploded time.
739 * @param pTimeSpec The time spec to exploded (UTC).
740 */
741RTDECL(PRTTIME) RTTimeLocalExplode(PRTTIME pTime, PCRTTIMESPEC pTimeSpec);
742
743/**
744 * Normalizes the fields of a time structure containing local time.
745 *
746 * See RTTimeNormalize for details.
747 *
748 * @returns pTime on success.
749 * @returns NULL if the data is invalid.
750 * @param pTime The time structure to normalize.
751 */
752RTDECL(PRTTIME) RTTimeLocalNormalize(PRTTIME pTime);
753
754/**
755 * Converts a time structure to UTC, relying on UTC offset information
756 * if it contains local time.
757 *
758 * @returns pTime on success.
759 * @returns NULL if the data is invalid.
760 * @param pTime The time structure to convert.
761 */
762RTDECL(PRTTIME) RTTimeConvertToZulu(PRTTIME pTime);
763
764/**
765 * Converts a time spec to a ISO date string.
766 *
767 * @returns psz on success.
768 * @returns NULL on buffer underflow.
769 * @param pTime The time. Caller should've normalized this.
770 * @param psz Where to store the string.
771 * @param cb The size of the buffer.
772 */
773RTDECL(char *) RTTimeToString(PCRTTIME pTime, char *psz, size_t cb);
774
775/**
776 * Attempts to convert an ISO date string to a time structure.
777 *
778 * We're a little forgiving with zero padding, unspecified parts, and leading
779 * and trailing spaces.
780 *
781 * @retval pTime on success,
782 * @retval NULL on failure.
783 * @param pTime Where to store the time on success.
784 * @param pszString The ISO date string to convert.
785 */
786RTDECL(PRTTIME) RTTimeFromString(PRTTIME pTime, const char *pszString);
787
788/**
789 * Checks if a year is a leap year or not.
790 *
791 * @returns true if it's a leap year.
792 * @returns false if it's a common year.
793 * @param i32Year The year in question.
794 */
795RTDECL(bool) RTTimeIsLeapYear(int32_t i32Year);
796
797/**
798 * Compares two normalized time structures.
799 *
800 * @retval 0 if equal.
801 * @retval -1 if @a pLeft is earlier than @a pRight.
802 * @retval 1 if @a pRight is earlier than @a pLeft.
803 *
804 * @param pLeft The left side time. NULL is accepted.
805 * @param pRight The right side time. NULL is accepted.
806 *
807 * @note A NULL time is considered smaller than anything else. If both are
808 * NULL, they are considered equal.
809 */
810RTDECL(int) RTTimeCompare(PCRTTIME pLeft, PCRTTIME pRight);
811
812/**
813 * Gets the current nanosecond timestamp.
814 *
815 * @returns nanosecond timestamp.
816 */
817RTDECL(uint64_t) RTTimeNanoTS(void);
818
819/**
820 * Gets the current millisecond timestamp.
821 *
822 * @returns millisecond timestamp.
823 */
824RTDECL(uint64_t) RTTimeMilliTS(void);
825
826/**
827 * Debugging the time api.
828 *
829 * @returns the number of 1ns steps which has been applied by RTTimeNanoTS().
830 */
831RTDECL(uint32_t) RTTimeDbgSteps(void);
832
833/**
834 * Debugging the time api.
835 *
836 * @returns the number of times the TSC interval expired RTTimeNanoTS().
837 */
838RTDECL(uint32_t) RTTimeDbgExpired(void);
839
840/**
841 * Debugging the time api.
842 *
843 * @returns the number of bad previous values encountered by RTTimeNanoTS().
844 */
845RTDECL(uint32_t) RTTimeDbgBad(void);
846
847/**
848 * Debugging the time api.
849 *
850 * @returns the number of update races in RTTimeNanoTS().
851 */
852RTDECL(uint32_t) RTTimeDbgRaces(void);
853
854/** @name RTTimeNanoTS GIP worker functions, for TM.
855 * @{ */
856/** Pointer to a RTTIMENANOTSDATA structure. */
857typedef struct RTTIMENANOTSDATA *PRTTIMENANOTSDATA;
858
859/**
860 * Nanosecond timestamp data.
861 *
862 * This is used to keep track of statistics and callback so IPRT
863 * and TM (VirtualBox) can share code.
864 *
865 * @remark Keep this in sync with the assembly version in timesupA.asm.
866 */
867typedef struct RTTIMENANOTSDATA
868{
869 /** Where the previous timestamp is stored.
870 * This is maintained to ensure that time doesn't go backwards or anything. */
871 uint64_t volatile *pu64Prev;
872
873 /**
874 * Helper function that's used by the assembly routines when something goes bust.
875 *
876 * @param pData Pointer to this structure.
877 * @param u64NanoTS The calculated nano ts.
878 * @param u64DeltaPrev The delta relative to the previously returned timestamp.
879 * @param u64PrevNanoTS The previously returned timestamp (as it was read it).
880 */
881 DECLCALLBACKMEMBER(void, pfnBad)(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS);
882
883 /**
884 * Callback for when rediscovery is required.
885 *
886 * @returns Nanosecond timestamp.
887 * @param pData Pointer to this structure.
888 */
889 DECLCALLBACKMEMBER(uint64_t, pfnRediscover)(PRTTIMENANOTSDATA pData);
890
891 /**
892 * Callback for when some CPU index related stuff goes wrong.
893 *
894 * @returns Nanosecond timestamp.
895 * @param pData Pointer to this structure.
896 * @param idApic The APIC ID if available, otherwise (UINT16_MAX-1).
897 * @param iCpuSet The CPU set index if available, otherwise
898 * (UINT16_MAX-1).
899 * @param iGipCpu The GIP CPU array index if available, otherwise
900 * (UINT16_MAX-1).
901 */
902 DECLCALLBACKMEMBER(uint64_t, pfnBadCpuIndex)(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu);
903
904 /** Number of 1ns steps because of overshooting the period. */
905 uint32_t c1nsSteps;
906 /** The number of times the interval expired (overflow). */
907 uint32_t cExpired;
908 /** Number of "bad" previous values. */
909 uint32_t cBadPrev;
910 /** The number of update races. */
911 uint32_t cUpdateRaces;
912} RTTIMENANOTSDATA;
913
914#ifndef IN_RING3
915/**
916 * The Ring-3 layout of the RTTIMENANOTSDATA structure.
917 */
918typedef struct RTTIMENANOTSDATAR3
919{
920 R3PTRTYPE(uint64_t volatile *) pu64Prev;
921 DECLR3CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
922 DECLR3CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
923 DECLR3CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
924 uint32_t c1nsSteps;
925 uint32_t cExpired;
926 uint32_t cBadPrev;
927 uint32_t cUpdateRaces;
928} RTTIMENANOTSDATAR3;
929#else
930typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR3;
931#endif
932
933#ifndef IN_RING0
934/**
935 * The Ring-3 layout of the RTTIMENANOTSDATA structure.
936 */
937typedef struct RTTIMENANOTSDATAR0
938{
939 R0PTRTYPE(uint64_t volatile *) pu64Prev;
940 DECLR0CALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
941 DECLR0CALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
942 DECLR0CALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
943 uint32_t c1nsSteps;
944 uint32_t cExpired;
945 uint32_t cBadPrev;
946 uint32_t cUpdateRaces;
947} RTTIMENANOTSDATAR0;
948#else
949typedef RTTIMENANOTSDATA RTTIMENANOTSDATAR0;
950#endif
951
952#ifndef IN_RC
953/**
954 * The RC layout of the RTTIMENANOTSDATA structure.
955 */
956typedef struct RTTIMENANOTSDATARC
957{
958 RCPTRTYPE(uint64_t volatile *) pu64Prev;
959 DECLRCCALLBACKMEMBER(void, pfnBad,(PRTTIMENANOTSDATA pData, uint64_t u64NanoTS, uint64_t u64DeltaPrev, uint64_t u64PrevNanoTS));
960 DECLRCCALLBACKMEMBER(uint64_t, pfnRediscover,(PRTTIMENANOTSDATA pData));
961 DECLRCCALLBACKMEMBER(uint64_t, pfnBadCpuIndex,(PRTTIMENANOTSDATA pData, uint16_t idApic, uint16_t iCpuSet, uint16_t iGipCpu));
962 uint32_t c1nsSteps;
963 uint32_t cExpired;
964 uint32_t cBadPrev;
965 uint32_t cUpdateRaces;
966} RTTIMENANOTSDATARC;
967#else
968typedef RTTIMENANOTSDATA RTTIMENANOTSDATARC;
969#endif
970
971/** Internal RTTimeNanoTS worker (assembly). */
972typedef DECLCALLBACK(uint64_t) FNTIMENANOTSINTERNAL(PRTTIMENANOTSDATA pData);
973/** Pointer to an internal RTTimeNanoTS worker (assembly). */
974typedef FNTIMENANOTSINTERNAL *PFNTIMENANOTSINTERNAL;
975RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarNoDelta(PRTTIMENANOTSDATA pData);
976RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarNoDelta(PRTTIMENANOTSDATA pData);
977#ifdef IN_RING3
978RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseApicId(PRTTIMENANOTSDATA pData);
979RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
980RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
981RTDECL(uint64_t) RTTimeNanoTSLegacyAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
982RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
983RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
984RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
985RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseApicId(PRTTIMENANOTSDATA pData);
986RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscp(PRTTIMENANOTSDATA pData);
987RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseRdtscpGroupChNumCl(PRTTIMENANOTSDATA pData);
988RTDECL(uint64_t) RTTimeNanoTSLFenceAsyncUseIdtrLim(PRTTIMENANOTSDATA pData);
989RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseApicId(PRTTIMENANOTSDATA pData);
990RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseRdtscp(PRTTIMENANOTSDATA pData);
991RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDeltaUseIdtrLim(PRTTIMENANOTSDATA pData);
992#else
993RTDECL(uint64_t) RTTimeNanoTSLegacyAsync(PRTTIMENANOTSDATA pData);
994RTDECL(uint64_t) RTTimeNanoTSLegacySyncInvarWithDelta(PRTTIMENANOTSDATA pData);
995RTDECL(uint64_t) RTTimeNanoTSLFenceAsync(PRTTIMENANOTSDATA pData);
996RTDECL(uint64_t) RTTimeNanoTSLFenceSyncInvarWithDelta(PRTTIMENANOTSDATA pData);
997#endif
998
999/** @} */
1000
1001
1002/**
1003 * Gets the current nanosecond timestamp.
1004 *
1005 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
1006 * resolution or performance optimizations.
1007 *
1008 * @returns nanosecond timestamp.
1009 */
1010RTDECL(uint64_t) RTTimeSystemNanoTS(void);
1011
1012/**
1013 * Gets the current millisecond timestamp.
1014 *
1015 * This differs from RTTimeNanoTS in that it will use system APIs and not do any
1016 * resolution or performance optimizations.
1017 *
1018 * @returns millisecond timestamp.
1019 */
1020RTDECL(uint64_t) RTTimeSystemMilliTS(void);
1021
1022/**
1023 * Get the nanosecond timestamp relative to program startup.
1024 *
1025 * @returns Timestamp relative to program startup.
1026 */
1027RTDECL(uint64_t) RTTimeProgramNanoTS(void);
1028
1029/**
1030 * Get the microsecond timestamp relative to program startup.
1031 *
1032 * @returns Timestamp relative to program startup.
1033 */
1034RTDECL(uint64_t) RTTimeProgramMicroTS(void);
1035
1036/**
1037 * Get the millisecond timestamp relative to program startup.
1038 *
1039 * @returns Timestamp relative to program startup.
1040 */
1041RTDECL(uint64_t) RTTimeProgramMilliTS(void);
1042
1043/**
1044 * Get the second timestamp relative to program startup.
1045 *
1046 * @returns Timestamp relative to program startup.
1047 */
1048RTDECL(uint32_t) RTTimeProgramSecTS(void);
1049
1050/**
1051 * Get the RTTimeNanoTS() of when the program started.
1052 *
1053 * @returns Program startup timestamp.
1054 */
1055RTDECL(uint64_t) RTTimeProgramStartNanoTS(void);
1056
1057
1058/**
1059 * Time zone information.
1060 */
1061typedef struct RTTIMEZONEINFO
1062{
1063 /** Unix time zone name (continent/country[/city]|). */
1064 const char *pszUnixName;
1065 /** Windows time zone name. */
1066 const char *pszWindowsName;
1067 /** The length of the unix time zone name. */
1068 uint8_t cchUnixName;
1069 /** The length of the windows time zone name. */
1070 uint8_t cchWindowsName;
1071 /** Two letter country/territory code if applicable, otherwise 'ZZ'. */
1072 char szCountry[3];
1073 /** Two letter windows country/territory code if applicable.
1074 * Empty string if no windows mapping. */
1075 char szWindowsCountry[3];
1076#if 0 /* Add when needed and it's been extracted. */
1077 /** The standard delta in minutes (add to UTC). */
1078 int16_t cMinStdDelta;
1079 /** The daylight saving time delta in minutes (add to UTC). */
1080 int16_t cMinDstDelta;
1081#endif
1082 /** closest matching windows time zone index. */
1083 uint32_t idxWindows;
1084 /** Flags, RTTIMEZONEINFO_F_XXX. */
1085 uint32_t fFlags;
1086} RTTIMEZONEINFO;
1087/** Pointer to time zone info. */
1088typedef RTTIMEZONEINFO const *PCRTTIMEZONEINFO;
1089
1090/** @name RTTIMEZONEINFO_F_XXX - time zone info flags.
1091 * @{ */
1092/** Indicates golden mapping entry for a windows time zone name. */
1093#define RTTIMEZONEINFO_F_GOLDEN RT_BIT_32(0)
1094/** @} */
1095
1096/**
1097 * Looks up static time zone information by unix name.
1098 *
1099 * @returns Pointer to info entry if found, NULL if not.
1100 * @param pszName The unix zone name (TZ).
1101 */
1102RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByUnixName(const char *pszName);
1103
1104/**
1105 * Looks up static time zone information by window name.
1106 *
1107 * @returns Pointer to info entry if found, NULL if not.
1108 * @param pszName The windows zone name (reg key).
1109 */
1110RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByWindowsName(const char *pszName);
1111
1112/**
1113 * Looks up static time zone information by windows index.
1114 *
1115 * @returns Pointer to info entry if found, NULL if not.
1116 * @param idxZone The windows timezone index.
1117 */
1118RTDECL(PCRTTIMEZONEINFO) RTTimeZoneGetInfoByWindowsIndex(uint32_t idxZone);
1119
1120/**
1121 * Get the current time zone (TZ).
1122 *
1123 * @returns IPRT status code.
1124 * @param pszName Where to return the time zone name.
1125 * @param cbName The size of the name buffer.
1126 */
1127RTDECL(int) RTTimeZoneGetCurrent(char *pszName, size_t cbName);
1128
1129/** @} */
1130
1131RT_C_DECLS_END
1132
1133#endif
1134
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