time.c revision ff8cd3afa7f900d7986ccbc3638235cb8ad6f1ec
499b34cea04a46823d003d4c0520c8b03e8513cbBrian Wellington/*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1998-2001 Internet Software Consortium.
4c1132f34493327abc632196f5876a89aa573687Bob Halley *
4c1132f34493327abc632196f5876a89aa573687Bob Halley * Permission to use, copy, modify, and distribute this software for any
4c1132f34493327abc632196f5876a89aa573687Bob Halley * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
15a44745412679c30a6d022733925af70a38b715David Lawrence * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
15a44745412679c30a6d022733925af70a38b715David Lawrence * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
15a44745412679c30a6d022733925af70a38b715David Lawrence * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
5c6762838c9e423753723ec2a963164e3d66ac32Mark Andrews */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
f41f183f628a148860a6d1f0070208cddd45b0c6Bob Halley/* $Id: time.c,v 1.26 2001/08/31 22:31:17 gson Exp $ */
f41f183f628a148860a6d1f0070208cddd45b0c6Bob Halley
f41f183f628a148860a6d1f0070208cddd45b0c6Bob Halley/*
f41f183f628a148860a6d1f0070208cddd45b0c6Bob Halley * Windows has a different epoch than Unix. Therefore this code sets the epoch
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * value to the Unix epoch. Care should be used when using these routines to
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley * ensure that this difference is taken into account. System and File times
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley * may require adjusting for this when modifying any time value that needs
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley * to be an absolute Windows time.
c2bc56dc65b4b103a5600565680eb5f33fa4c90bMark Andrews *
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley * Currently only epoch-specific code and the isc_time_seconds
51917258dbb23cfe6069ae1cf2b7fc5aefc1e0c2Bob Halley * and isc_time_secondsastimet use the epoch-adjusted code.
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley */
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley#include <config.h>
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
b6d52ee5bea1b9d9074698e693b49ce96edff47bMark Andrews#include <errno.h>
b6d52ee5bea1b9d9074698e693b49ce96edff47bMark Andrews#include <limits.h>
b6d52ee5bea1b9d9074698e693b49ce96edff47bMark Andrews#include <stddef.h>
b6d52ee5bea1b9d9074698e693b49ce96edff47bMark Andrews#include <stdlib.h>
c45abd11bb68005d8a5c56c14b16f4184c3e057dMichael Graff#include <string.h>
c45abd11bb68005d8a5c56c14b16f4184c3e057dMichael Graff#include <time.h>
a685d9c3b608eb768d237f20e8e8b1c5d3902146David Lawrence
feb08cecf318bba330437cfcb725f48d999804d8James Brister#include <windows.h>
81aea2f2d3eac0515eb29449977ad50752f42a39Mark Andrews
81aea2f2d3eac0515eb29449977ad50752f42a39Mark Andrews#include <isc/assertions.h>
81aea2f2d3eac0515eb29449977ad50752f42a39Mark Andrews#include <isc/time.h>
81aea2f2d3eac0515eb29449977ad50752f42a39Mark Andrews#include <isc/util.h>
81aea2f2d3eac0515eb29449977ad50752f42a39Mark Andrews
81aea2f2d3eac0515eb29449977ad50752f42a39Mark Andrews/*
81aea2f2d3eac0515eb29449977ad50752f42a39Mark Andrews * struct FILETIME uses "100-nanoseconds intervals".
65c4736d9c0ebc6d9b1d991593b55566909da9cdBrian Wellington * NS / S = 1000000000 (10^9).
fc80027fb54b501cdd88461bf879d078259e0226David Lawrence * While it is reasonably obvious that this makes the needed
5c6762838c9e423753723ec2a963164e3d66ac32Mark Andrews * conversion factor 10^7, it is coded this way for additional clarity.
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson */
911ed0d3bee586b3bec42cb6c376d5cc6c0e1e24Brian Wellington#define NS_PER_S 1000000000
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define NS_INTERVAL 100
911ed0d3bee586b3bec42cb6c376d5cc6c0e1e24Brian Wellington#define INTERVALS_PER_S (NS_PER_S / NS_INTERVAL)
911ed0d3bee586b3bec42cb6c376d5cc6c0e1e24Brian Wellington#define UINT64_MAX _UI64_MAX
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
3cd88f71b01833d5c2474638854dfa5c4244a22aBrian Wellington/***
3cd88f71b01833d5c2474638854dfa5c4244a22aBrian Wellington *** Absolute Times
e7a4f58d55042cbc981a70b5071aaea46b9ebf7fAndreas Gustafsson ***/
ce1f5b8d0ae5936fd187c1f414ff12a7e3b0aa37Andreas Gustafsson
850d70818503ca1b0f98c9c70b16b51e789fd705Andreas Gustafssonstatic isc_time_t epoch = { 0, 0 };
5c6762838c9e423753723ec2a963164e3d66ac32Mark Andrewsisc_time_t *isc_time_epoch = &epoch;
5c6762838c9e423753723ec2a963164e3d66ac32Mark Andrews
5c6762838c9e423753723ec2a963164e3d66ac32Mark Andrewsvoid
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob HalleyTimetToFileTime(time_t t, LPFILETIME pft) {
fc80027fb54b501cdd88461bf879d078259e0226David Lawrence LONGLONG i;
49a940dc68b30d9e4f9e1bd3c0503d8b90bb1726Mark Andrews
6017f424ee3c02d7f22132c77576ea38542fa949Andreas Gustafsson i = Int32x32To64(t, 10000000) + 116444736000000000;
911ed0d3bee586b3bec42cb6c376d5cc6c0e1e24Brian Wellington pft->dwLowDateTime = (DWORD) i;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews pft->dwHighDateTime = (DWORD) (i >>32);
911ed0d3bee586b3bec42cb6c376d5cc6c0e1e24Brian Wellington}
911ed0d3bee586b3bec42cb6c376d5cc6c0e1e24Brian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews/***
3cd88f71b01833d5c2474638854dfa5c4244a22aBrian Wellington *** Intervals
3cd88f71b01833d5c2474638854dfa5c4244a22aBrian Wellington ***/
e7a4f58d55042cbc981a70b5071aaea46b9ebf7fAndreas Gustafsson
ce1f5b8d0ae5936fd187c1f414ff12a7e3b0aa37Andreas Gustafssonstatic isc_interval_t zero_interval = { 0 };
850d70818503ca1b0f98c9c70b16b51e789fd705Andreas Gustafssonisc_interval_t *isc_interval_zero = &zero_interval;
18d110413cf6416eb339c169b99159d09f690da1Brian Wellington
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrewsvoid
438b80a31b2d58b99970914f50d0a84bf9f832a5Brian Wellingtonisc_interval_set(isc_interval_t *i, unsigned int seconds,
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews unsigned int nanoseconds)
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews{
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley REQUIRE(i != NULL);
d2b5fe92a4755ce67f2dd6050955782b4fd6b3f3Mark Andrews REQUIRE(nanoseconds < NS_PER_S);
d2b5fe92a4755ce67f2dd6050955782b4fd6b3f3Mark Andrews
d2b5fe92a4755ce67f2dd6050955782b4fd6b3f3Mark Andrews i->interval = (LONGLONG)seconds * INTERVALS_PER_S
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley + nanoseconds / NS_INTERVAL;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley}
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halleyisc_boolean_t
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halleyisc_interval_iszero(isc_interval_t *i) {
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley REQUIRE(i != NULL);
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley if (i->interval == 0)
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley return (ISC_TRUE);
139154bd9894495042f4e748f554e9c8b98b7598Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley return (ISC_FALSE);
193738b819e3c699f9edd18864a6810fcfcec855Andreas Gustafsson}
fd35453765c6494d077edca44f4d998af5fd4cfaDavid Lawrence
fd35453765c6494d077edca44f4d998af5fd4cfaDavid Lawrence
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halleyvoid
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halleyisc_time_set(isc_time_t *t, unsigned int seconds, unsigned int nanoseconds) {
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley ULARGE_INTEGER i;
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley REQUIRE(t != NULL);
881702c9c0079cd48a45054fd90d043f3a8b7e11Mark Andrews REQUIRE(nanoseconds < NS_PER_S);
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley i.QuadPart = (LONGLONG)seconds * INTERVALS_PER_S
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley + nanoseconds / NS_INTERVAL;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley t->absolute.dwLowDateTime = i.LowPart
922e6a3c2ac4ef900dd9dc99f0cc137f18372583Andreas Gustafsson + epoch.absolute.dwLowDateTime;
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley t->absolute.dwHighDateTime = i.HighPart
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley + epoch.absolute.dwHighDateTime;
a2f3208f7f754cbc5156a1d798ae06d8f3546be2Bob Halley
a5d43b72413db3edd6b36a58f9bdf2cf6ff692f2Bob Halley}
4880900113e4d0f17884f3fbdbf4c302e3f9ea91Bob Halley
fd35453765c6494d077edca44f4d998af5fd4cfaDavid Lawrencevoid
c8a42d6d81ff2fd9ad7fac94d4b85323554493c0Bob Halleyisc_time_initepoch() {
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrews TimetToFileTime(0, &epoch.absolute);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews}
6ef838d427c1ea858d2f09194a369134babf8b98Mark Andrews
6ef838d427c1ea858d2f09194a369134babf8b98Mark Andrewsvoid
6ef838d427c1ea858d2f09194a369134babf8b98Mark Andrewsisc_time_settoepoch(isc_time_t *t) {
6ef838d427c1ea858d2f09194a369134babf8b98Mark Andrews REQUIRE(t != NULL);
6d831cd0baf7dd2c133f7f9cbf295f3d80cf63a7David Lawrence
6d831cd0baf7dd2c133f7f9cbf295f3d80cf63a7David Lawrence t->absolute.dwLowDateTime = epoch.absolute.dwLowDateTime;
dac2799ea19735503a4d27f517d821aea210e594Andreas Gustafsson t->absolute.dwHighDateTime = epoch.absolute.dwHighDateTime;
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley}
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
6d7585b3e948dd31bf78321d83ac0e024f44a71bMark Andrewsisc_boolean_t
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halleyisc_time_isepoch(isc_time_t *t) {
6d7585b3e948dd31bf78321d83ac0e024f44a71bMark Andrews REQUIRE(t != NULL);
6d7585b3e948dd31bf78321d83ac0e024f44a71bMark Andrews
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley if (t->absolute.dwLowDateTime == epoch.absolute.dwLowDateTime &&
6d7585b3e948dd31bf78321d83ac0e024f44a71bMark Andrews t->absolute.dwHighDateTime == epoch.absolute.dwHighDateTime)
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halley return (ISC_TRUE);
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halley
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halley return (ISC_FALSE);
94a3bcd132e515b4baa0884ba9dd0f361d2e17bcMark Andrews}
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halley
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halleyisc_result_t
4fd3e3482c7e4ce01e2cf28f13e0152c8e50d746Mark Andrewsisc_time_now(isc_time_t *t) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
6d5dcd0dc9bdbd679282b1ffc47987d24c3a1346Bob Halley REQUIRE(t != NULL);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews GetSystemTimeAsFileTime(&t->absolute);
139154bd9894495042f4e748f554e9c8b98b7598Bob Halley
bb556a9bf3a15c7160fa4f1b71773ce12b1bedf6Bob Halley return (ISC_R_SUCCESS);
64e41159a919b0711321fe688ca5da4f4d1b7d80Bob Halley}
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halley
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halleyisc_result_t
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halleyisc_time_nowplusinterval(isc_time_t *t, isc_interval_t *i) {
fe37278859bce157001cca14cdfa3a761b0d5012Mark Andrews ULARGE_INTEGER i1;
1471a520e59ac12b413afa8d8b3158a87af97aa6Bob Halley
5c6762838c9e423753723ec2a963164e3d66ac32Mark Andrews REQUIRE(t != NULL);
798c83548f89091e3994ca5a9c8c7e9caaf89d10Mark Andrews REQUIRE(i != NULL);
798c83548f89091e3994ca5a9c8c7e9caaf89d10Mark Andrews
GetSystemTimeAsFileTime(&t->absolute);
i1.LowPart = t->absolute.dwLowDateTime;
i1.HighPart = t->absolute.dwHighDateTime;
if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
return (ISC_R_RANGE);
i1.QuadPart += i->interval;
t->absolute.dwLowDateTime = i1.LowPart;
t->absolute.dwHighDateTime = i1.HighPart;
return (ISC_R_SUCCESS);
}
int
isc_time_compare(isc_time_t *t1, isc_time_t *t2) {
REQUIRE(t1 != NULL && t2 != NULL);
return ((int)CompareFileTime(&t1->absolute, &t2->absolute));
}
isc_result_t
isc_time_add(isc_time_t *t, isc_interval_t *i, isc_time_t *result) {
ULARGE_INTEGER i1;
REQUIRE(t != NULL && i != NULL && result != NULL);
i1.LowPart = t->absolute.dwLowDateTime;
i1.HighPart = t->absolute.dwHighDateTime;
if (UINT64_MAX - i1.QuadPart < (unsigned __int64)i->interval)
return (ISC_R_RANGE);
i1.QuadPart += i->interval;
result->absolute.dwLowDateTime = i1.LowPart;
result->absolute.dwHighDateTime = i1.HighPart;
return (ISC_R_SUCCESS);
}
isc_result_t
isc_time_subtract(isc_time_t *t, isc_interval_t *i, isc_time_t *result) {
ULARGE_INTEGER i1;
REQUIRE(t != NULL && i != NULL && result != NULL);
i1.LowPart = t->absolute.dwLowDateTime;
i1.HighPart = t->absolute.dwHighDateTime;
if (i1.QuadPart < (unsigned __int64) i->interval)
return (ISC_R_RANGE);
i1.QuadPart -= i->interval;
result->absolute.dwLowDateTime = i1.LowPart;
result->absolute.dwHighDateTime = i1.HighPart;
return (ISC_R_SUCCESS);
}
isc_uint64_t
isc_time_microdiff(isc_time_t *t1, isc_time_t *t2) {
ULARGE_INTEGER i1, i2;
LONGLONG i3;
REQUIRE(t1 != NULL && t2 != NULL);
i1.LowPart = t1->absolute.dwLowDateTime;
i1.HighPart = t1->absolute.dwHighDateTime;
i2.LowPart = t2->absolute.dwLowDateTime;
i2.HighPart = t2->absolute.dwHighDateTime;
if (i1.QuadPart <= i2.QuadPart)
return (0);
/*
* Convert to microseconds.
*/
i3 = (i1.QuadPart - i2.QuadPart) / 10;
return (i3);
}
/*
* Note that the value returned is the seconds relative to the Unix
* epoch rather than the seconds since Windows epoch. This is for
* compatibility with the Unix side.
*/
isc_uint32_t
isc_time_seconds(isc_time_t *t) {
ULARGE_INTEGER i;
REQUIRE(t != NULL);
i.LowPart = t->absolute.dwLowDateTime -
epoch.absolute.dwLowDateTime;
i.HighPart = t->absolute.dwHighDateTime -
epoch.absolute.dwHighDateTime;
return ((isc_uint32_t)(i.QuadPart / INTERVALS_PER_S));
}
isc_result_t
isc_time_secondsastimet(isc_time_t *t, time_t *secondsp) {
ULARGE_INTEGER i1, i2;
time_t seconds;
REQUIRE(t != NULL);
i1.LowPart = t->absolute.dwLowDateTime;
i1.HighPart = t->absolute.dwHighDateTime;
/*
* Get the time_t zero equivalent in FILETIME
* The zero point for FILETIME is 1 January, 1601
* while for timet it is 1 January, 1970
*/
i1.LowPart -= epoch.absolute.dwLowDateTime;
i1.HighPart -= epoch.absolute.dwHighDateTime;
i1.QuadPart /= INTERVALS_PER_S;
/*
* Ensure that the number of seconds can be represented by a time_t.
* Since the number seconds is an unsigned int and since time_t is
* mostly opaque, this is trickier than it seems. (This standardized
* opaqueness of time_t is *very* * frustrating; time_t is not even
* limited to being an integral type.) Thought it is known at the
* time of this writing that time_t is a signed long on the Win32
* platform, the full treatment is given to figuring out if things
* fit to allow for future Windows platforms where time_t is *not*
* a signed long, or where perhaps a signed long is longer than
* it currently is.
*/
seconds = (time_t)i1.QuadPart;
/*
* First, only do the range tests if the type of size_t is integral.
* Float/double easily include the maximum possible values.
*/
if ((time_t)0.5 != 0.5) {
/*
* Did all the bits make it in?
*/
if ((seconds & i1.QuadPart) != i1.QuadPart)
return (ISC_R_RANGE);
/*
* Is time_t signed with the high bit set?
*
* The first test (the sizeof comparison) determines
* whether we can even deduce the signedness of time_t
* by using ANSI's rule about integer conversion to
* wider integers.
*
* The second test uses that ANSI rule to see whether
* the value of time_t was sign extended into QuadPart.
* If the test is true, then time_t is signed.
*
* The final test ensures the high bit is not set, or
* the value is negative and hence there is a range error.
*/
if (sizeof(time_t) < sizeof(i2.QuadPart) &&
((i2.QuadPart = (time_t)-1) ^ (time_t)-1) != 0 &&
(seconds & (1 << (sizeof(time_t) * 8 - 1))) != 0)
return (ISC_R_RANGE);
/*
* Last test ... the size of time_t is >= that of i2.QuadPart,
* so we can't determine its signedness. Unconditionally
* declare anything with the high bit set as out of range.
* Since even the maxed signed value is ludicrously far from
* when this is being written, this rule shall not impact
* anything for all intents and purposes.
*
* How far? Well ... if FILETIME is in 100 ns intervals since
* 1600, and a QuadPart can store 9223372036854775808 such
* intervals when interpreted as signed (ie, if sizeof(time_t)
* == sizeof(QuadPart) but time_t is signed), that means
* 9223372036854775808 / INTERVALS_PER_S = 922,337,203,685
* seconds. That number divided by 60 * 60 * 24 * 365 seconds
* per year means a signed time_t can store at least 29,247
* years, with only 400 of those years used up since 1600 as I
* write this in May, 2000.
*
* (Real date calculations are of course incredibly more
* complex; I'm only describing the approximate scale of
* the numbers involved here.)
*
* If the Galactic Federation is still running libisc's time
* libray on a Windows platform in the year 27647 A.D., then
* feel free to hunt down my greatgreatgreatgreatgreat(etc)
* grandchildren and whine at them about what I did.
*/
if ((seconds & (1 << (sizeof(time_t) * 8 - 1))) != 0)
return (ISC_R_RANGE);
}
*secondsp = seconds;
return (ISC_R_SUCCESS);
}
isc_uint32_t
isc_time_nanoseconds(isc_time_t *t) {
SYSTEMTIME st;
/*
* Convert the time to a SYSTEMTIME structure and the grab the
* milliseconds
*/
FileTimeToSystemTime(&t->absolute, &st);
return ((isc_uint32_t)(st.wMilliseconds * 1000000));
}
void
isc_time_formattimestamp(const isc_time_t *t, char *buf, unsigned int len) {
FILETIME localft;
SYSTEMTIME st;
static const char *months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
REQUIRE(len > 0);
if (FileTimeToLocalFileTime(&t->absolute, &localft) &&
FileTimeToSystemTime(&localft, &st))
{
snprintf(buf, len, "%s %2u %02u:%02u:%02u.%03u",
months[st.wMonth], st.wDay, st.wHour, st.wMinute,
st.wSecond, st.wMilliseconds);
} else {
snprintf(buf, len, "<bad time>");
}
}