Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

what is the best way to get microseconds of time on Windows in C or C++ ?

1,570 views
Skip to first unread message

Lynn McGuire

unread,
Nov 3, 2022, 9:14:23 PM11/3/22
to
What is the best way to get microseconds of time on Windows in C or C++
? I am currently using the following code to get the current time:

std::time_t t = std::time (0); // get time now
std::tm * now = std::localtime ( & t);
integer iyear = now -> tm_year + 1900;
integer imonth = now -> tm_mon + 1;
integer iday = now -> tm_mday;
integer ihour = now -> tm_hour;
integer imin = now -> tm_min;
integer isec = now -> tm_sec;
integer ihund = 0;

Thanks,
Lynn

Lynn McGuire

unread,
Nov 4, 2022, 1:07:12 AM11/4/22
to
On 11/3/2022 8:51 PM, DFS wrote:
> https://learn.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps
>
>
> I used it like this:
> ----------------------------------------------------------------
> LARGE_INTEGER frequency,start,end;
>
> //calc elapsed time
> double elapsedtime(LARGE_INTEGER startingtimer)
> {
>   QueryPerformanceCounter(&end);
>   return (end.QuadPart - startingtimer.QuadPart) /
> (double)frequency.QuadPart;
> }
>
>
> int main(void)
> {
>
>     //turn on Windows program timing
>     QueryPerformanceFrequency(&frequency);
>
>     //start timing a piece of code
>     QueryPerformanceCounter(&start);
>     ...
>     ...
>     printf(" %.4fs to execute\n",elapsedtime(start));
>
> }
> ----------------------------------------------------------------

I forgot to add I would prefer a portable way if possible. I suspect
that is not possible though below the second resolution.

Thanks,
Lynn McGuire

Christian Gollwitzer

unread,
Nov 4, 2022, 3:03:24 AM11/4/22
to
HI Lynn,
Am 04.11.22 um 06:06 schrieb Lynn McGuire:
> On 11/3/2022 8:51 PM, DFS wrote:
>> On 11/3/2022 9:14 PM, Lynn McGuire wrote:
>>> What is the best way to get microseconds of time on Windows in C or
>>> C++ ?  I am currently using the following code to get the current time:
>>>

>> ----------------------------------------------------------------
>
> I forgot to add I would prefer a portable way if possible.  I suspect
> that is not possible though below the second resolution.
>

I fear it is not possible in a portable way. Here you can find some
description about how Tcl has solved this issue especially for Windows:

https://core.tcl-lang.org/tips/doc/trunk/tip/7.md

The implementation is here:

https://github.com/tcltk/tcl/blob/main/win/tclWinTime.c

and here for Unix:

https://github.com/tcltk/tcl/blob/main/unix/tclUnixTime.c

(BSD licensed, in any case)

Christian

Juha Nieminen

unread,
Nov 4, 2022, 3:37:13 AM11/4/22
to
In comp.lang.c++ Lynn McGuire <lynnmc...@gmail.com> wrote:
> What is the best way to get microseconds of time on Windows in C or C++

It's a bit unclear whether you mean "time in microseconds units" or "time
at the microseconds resolution".

Because the latter may not be even possible (portable or not). Just because
some time function returns time "in microseconds" that doesn't mean that it
uses microsecond resolution (in other words, the value it returns may well
change at longer intervals than every microsecond; probably *significantly*
longer intervals).

It is possible to get some kind of timing at the CPU clock cycle interval
(in most modern CPUs, at least), which is about as accurate as you can
possibly get, but I don't know if there are eg. some system functions that
will return elapsed clock cycles converted into the equivalent amount of
microseconds.

Öö Tiib

unread,
Nov 4, 2022, 4:23:40 AM11/4/22
to
I have such code snippet copy-pasted from somewhere about portable
since C++11.

auto t0 = std::chrono::high_resolution_clock::now();
auto nanosec = t0.time_since_epoch();

std::cout << nanosec.count() << " nanoseconds since epoch\n";
std::cout << nanosec.count() / (1000000000.0 * 60.0 * 60.0) << " hours since epoch\n";

As I rarely need nanoseconds haven't tried it everywhere
but at least looks portable.

Michael S

unread,
Nov 4, 2022, 6:12:12 AM11/4/22
to
Are you interested in absolute time or in measuring time intervals
for profiling and similar purposes?

For the former, usec resolution is obviously impossible, because
crystals that drive time measurement in your typical PC are not
very good and time adjustments via NTP are not particularly frequent.
Not just microseconds, even whole second are typically no good.

For the later, as long as measured intervals are relatively short
(no more than 10-20 msec) usec resolution is physically possible.

The most portable way is std::chrono::steady_clock.

Less portable way (unreliable with Windows+gcc under mingw)
but good with Windows+MSVC and Linux+gcc, is
std::chrono::high_resolution_clock

Another good way that is not portable in absolute sense, but
very portable between various x86 OSes and environments
is __rdtsc(). Except that I am not aware of portable way of
figuring out a duration of the tick. Well, except of calibration
followed by rounding to nearest 50MHz, but that method is
non-satisfactory.
In practice, quite often you just know the frequency. And
even more often non-portable way of finding it is good enough.

Scott Lurndal

unread,
Nov 4, 2022, 9:44:28 AM11/4/22
to

Keith Thompson

unread,
Nov 4, 2022, 12:08:17 PM11/4/22
to
The resolution of the time() function is unspecified (not even
implementation-defined). In practice, time_t is almost universally an
integer type representing seconds since some epoch, usually 1970-01-01
00:00:00 UTC, but it could even be floating-point.

C11 adds the type struct timespec and the function timespec_get() which
gives a result with a resolution of 1 nanosecond. A footnote in the
standard says:

Although a struct timespec object describes times with nanosecond
resolution, the available resolution is system dependent and may
even be greater than 1 second.

The standard says that struct timespec has the following members:

time_t tv_sec; // whole seconds — ≥ 0
long tv_nsec; // nanoseconds — [0, 999999999]

which strongly implies that the resulution of time_t is 1 second, but
the standard still doesn't say so. Possibly an implementation could use
different encodings for the time_t value from time() and the time_t
value from timespec_get(), though that's unlikely in practice.

clock() returns a value of type clock_t, which is typically double, but
that's also unspecified -- and it measures processor time, not wall
clock time.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

Lynn McGuire

unread,
Nov 4, 2022, 3:24:57 PM11/4/22
to
Get time at the microseconds resolution. My calculation engine creates
a bunch of temporary files and I use the time to create unique names for
those temporary files. Seconds should be good enough for uniqueness but
I like adding microseconds as a guarantee. Something like
uniquac1.out.009.20181972.20220912

Thanks,
Lynn

Lynn McGuire

unread,
Nov 4, 2022, 3:32:53 PM11/4/22
to
Thanks !

Lynn

Lynn McGuire

unread,
Nov 4, 2022, 3:33:53 PM11/4/22
to
Thanks !

Lynn


Lynn McGuire

unread,
Nov 4, 2022, 3:34:23 PM11/4/22
to
Thanks !

Lynn

Lynn McGuire

unread,
Nov 4, 2022, 3:36:04 PM11/4/22
to
Both measuring time intervals and the current time.

Thanks !

Lynn

Bonita Montero

unread,
Nov 4, 2022, 3:50:07 PM11/4/22
to
Use GetSystemTimeAsFileTime() and FileTimeToLocalFileTime() on
Windows or the time_t-capable Functions on Unix and this class:

Header:

#pragma once
#if defined(_MSC_VER)
#define NOMINMAX
#include <Windows.h>
#endif
#include <cstdint>
#include <compare>
#include <ctime>
#include <stdexcept>
#include <compare>
#include <memory>
#include <mutex>
#include <algorithm>
#include <vector>
#include <functional>
#include <atomic>

#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 26812) // prefer enum class over enum
#pragma warning(disable: 26495) // members not intitialized
#endif

struct st_timestamp
{
constexpr st_timestamp() = default;
st_timestamp( st_timestamp const & ) = default;
constexpr st_timestamp( std::uint64_t timestamp ) noexcept;
constexpr operator std::uint64_t() const noexcept;
constexpr explicit operator std::int64_t() const noexcept;
constexpr explicit operator bool() const noexcept;
constexpr st_timestamp &operator =( st_timestamp const & ) = default;
constexpr st_timestamp &operator =( std::uint64_t timestamp ) noexcept;
private:
std::uint64_t m_timestamp;
};

struct system_time
{
std::uint16_t year;
std::uint8_t weekday, month, day;
std::uint8_t hour, minute, second;
std::uint32_t ns100;
enum reason_t : uint8_t
{
TIMESTAMP_BEYOND_63_BIT = 1,
YEAR_OUT_OF_RANGE,
MONTH_OUT_OF_RANGE,
DAY_OUT_OF_RANGE,
HOUR_OUT_OF_RANGE,
MINUTE_OUT_OF_RANGE,
SECOND_OUT_OF_RANGE,
NS100_OUT_OF_RANGE,
TIMESTAMP_BEFORE_TIME_T,
WRONG_LEAP_SECOND
};
struct leap_second_t
{
std::uint16_t year;
bool jun30, dec31;
};
struct date_error : public std::invalid_argument
{
reason_t reason();
date_error() = delete;
date_error( date_error const & ) = delete;
private:
friend struct system_time;
date_error( reason_t reason );
reason_t m_reason;
};
system_time() {}
system_time( system_time const & ) = default;
system_time( std::uint16_t year, std::uint8_t month, std::uint8_t day,
std::uint8_t hour, std::uint8_t minute, std::uint8_t second,
std::uint32_t ns100 );
explicit system_time( st_timestamp ts );
system_time( struct tm const &tm );
#if defined(_MSC_VER)
system_time( SYSTEMTIME const &st );
#endif
operator st_timestamp() const;
st_timestamp to_timestamp( reason_t *reason = nullptr ) const noexcept;
system_time &operator =( st_timestamp ts );
void from_timestamp( st_timestamp ts, reason_t *reason = nullptr )
noexcept;
system_time &operator =( system_time const & ) = default;
operator tm() const;
struct tm to_tm( reason_t *reason ) const noexcept;
system_time &operator =( struct tm const &tm );
bool from_tm( struct tm const &tm, reason_t *reason ) noexcept;
#if defined(_MSC_VER)
operator SYSTEMTIME() const;
SYSTEMTIME to_systemtime( reason_t *reason ) const noexcept;
system_time &operator =( SYSTEMTIME const &st );
bool from_systemtime( SYSTEMTIME const &st, reason_t *reason ) noexcept;
#endif
bool adjust_weekday( reason_t *reason = nullptr ) noexcept;
static std::uint8_t get_weekday( st_timestamp timestamp ) noexcept;
static_assert(sizeof(time_t) == 8, "time_t must be 64 bit");
static time_t timestamp_to_time_t( st_timestamp ts, reason_t *reason =
nullptr ) noexcept;
static st_timestamp time_t_to_timestamp( time_t time, reason_t *reason
= nullptr ) noexcept;
static void leap_seconds( std::function<leap_second_t ( bool )> const
&fn );
private:
friend struct st_timestamp;
static std::atomic<std::shared_ptr<std::vector<leap_second_t>>>
g_leapSeconds;
static constexpr std::uint64_t
MILLISECOND = 10'000,
SECOND = 1'000 * MILLISECOND,
MINUTE = 60 * SECOND,
HOUR = 60 * MINUTE,
DAY = 24 * HOUR,
WEEK = 7 * DAY,
NON_LEAP_YEAR = 365 * DAY,
LEAP_YEAR = 366 * DAY,
FOUR_YEARS_W_LJ = LEAP_YEAR + 3 * NON_LEAP_YEAR,
FOUR_YEARS_WO_LJ = 4 * NON_LEAP_YEAR,
FIRST_QUARTER_CENTURY = 25 * FOUR_YEARS_W_LJ,
REMAINING_QUARTER_CENUTRIES = 25 * FOUR_YEARS_W_LJ - DAY,
FOUR_HUNDRED_YEARS = FIRST_QUARTER_CENTURY + 3 *
REMAINING_QUARTER_CENUTRIES,
TIME_T_IN_TIMESTAMP_BEGIN = 0x19DB1DED53E800,
LAST_TIMESTAMP_IN_TIME_T = 0xD69433CCD5,
LEAP_SECOND_BIT = std::numeric_limits<int64_t>::min();
};

constexpr st_timestamp::st_timestamp( std::uint64_t timestamp ) noexcept :
m_timestamp( timestamp )
{
}

constexpr st_timestamp::operator std::uint64_t() const noexcept
{
return m_timestamp & ~system_time::LEAP_SECOND_BIT;
}

constexpr st_timestamp::operator std::int64_t() const noexcept
{
return m_timestamp;
}

constexpr st_timestamp::operator bool() const noexcept
{
return m_timestamp & system_time::LEAP_SECOND_BIT;
}

constexpr st_timestamp &st_timestamp::operator =( std::uint64_t
timestamp ) noexcept
{
m_timestamp = timestamp;
return *this;
}

// may throw invalid_argument

inline system_time::system_time( st_timestamp ts )
{
*this = ts;
}

// may throw invalid_argument

inline system_time &system_time::operator =( st_timestamp ts )
{
reason_t reason;
from_timestamp( ts, &reason );
if( reason ) [[likely]]
throw date_error( reason );
return *this;
}


inline system_time::system_time( struct tm const &tm )
{
*this = tm;
}

#if defined(_MSC_VER)
inline system_time::system_time( SYSTEMTIME const &st )
{
*this = st;
}
#endif

inline typename system_time::reason_t system_time::date_error::reason()
{
return m_reason;
}

inline uint8_t system_time::get_weekday( st_timestamp ts ) noexcept
{
using namespace std;
return (uint32_t)(((uint64_t)ts - (uint64_t)ts / WEEK * WEEK) / DAY +
1) % 7;
}

// may throw date_error

inline std::strong_ordering operator <=>( system_time const &left,
system_time const &right )
{
return (std::uint64_t)(st_timestamp)left <=> (uint64_t)(st_timestamp)right;
}

// may throw date_error

inline std::strong_ordering operator <=>( system_time const &left,
st_timestamp right )
{
return (std::uint64_t)(st_timestamp)left <=> (std::uint64_t)right;
}

// may throw date_error

inline std::strong_ordering operator <=>( st_timestamp left, system_time
const &right )
{
return (std::uint64_t)left <=> (std::uint64_t)(st_timestamp)left;
}

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

// .cpp:

#include <stdexcept>
#include <cassert>
#include <limits>
#include <algorithm>
#include <array>
#include <system_error>
#include <functional>
#if defined(__cpp_lib_hardware_interference_size)
#include <new>
#endif
#include "system_time.h"

using namespace std;

#if defined(__cpp_lib_hardware_interference_size)
constexpr size_t CL_SIZE = std::hardware_destructive_interference_size;
#else
constexpr size_t CL_SIZE = 64;
#endif

constexpr bool SYSTEM_TIME_BINARY_SEARCH = false;

// may throw date_error

system_time::system_time( std::uint16_t year, std::uint8_t month,
std::uint8_t day, std::uint8_t hour, std::uint8_t minute, std::uint8_t
second, std::uint32_t ns100 )
{
this->year = year;
this->month = month;
this->day = day;
this->hour = hour;
this->minute = minute;
this->second = second;
this->ns100 = ns100;
this->weekday = get_weekday( (st_timestamp)*this );
}

// may throw date_error

void system_time::from_timestamp( st_timestamp ts, reason_t *reason )
noexcept
{
auto reasonableErr = [&]( reason_t retReason ) -> void
{
if( reason ) [[likely]]
*reason = retReason;
memset( this, 0, sizeof *this );
};
uint64_t tsCalc = (uint64_t)ts;
bool leapSecond = (bool)ts;
weekday = get_weekday( ts );
tsCalc += LEAP_YEAR; // 1601 - 1600 = leap year
uint16_t y400, y100, y4, y;
y400 = (uint16_t)(tsCalc / FOUR_HUNDRED_YEARS);
tsCalc -= y400 * FOUR_HUNDRED_YEARS;
bool isLeapYear;
auto leapQuad = [&]()
{
if( tsCalc >= LEAP_YEAR ) [[likely]]
// y >= 1
tsCalc -= LEAP_YEAR,
y = (uint16_t)(1 + tsCalc / NON_LEAP_YEAR), // 1 ... 3
tsCalc -= tsCalc / NON_LEAP_YEAR * NON_LEAP_YEAR,
isLeapYear = false;
else
// y == 0
y = 0,
isLeapYear = true;
};
if( tsCalc >= FIRST_QUARTER_CENTURY ) [[likely]]
{
// (y % 400) >= 100
y100 = (uint16_t)(1 + (tsCalc - FIRST_QUARTER_CENTURY) /
REMAINING_QUARTER_CENUTRIES); // 1 ... 3
tsCalc -= FIRST_QUARTER_CENTURY + (tsCalc - FIRST_QUARTER_CENTURY) /
REMAINING_QUARTER_CENUTRIES * REMAINING_QUARTER_CENUTRIES;
if( tsCalc >= FOUR_YEARS_WO_LJ ) [[likely]]
// (y % 400) >= 100 && (y % 100) >= 4
y4 = (uint16_t)(1 + (tsCalc - FOUR_YEARS_WO_LJ) / FOUR_YEARS_W_LJ),
// 1 ... 24
tsCalc -= FOUR_YEARS_WO_LJ + (tsCalc - FOUR_YEARS_WO_LJ) /
FOUR_YEARS_W_LJ * FOUR_YEARS_W_LJ,
leapQuad();
else
// (y % 400) >= 100 && (y % 100) < 4
y4 = 0,
y = (uint16_t)(tsCalc / NON_LEAP_YEAR),
tsCalc -= tsCalc / NON_LEAP_YEAR * NON_LEAP_YEAR,
isLeapYear = false;
}
else
// (y % 400) < 100
y100 = 0,
y4 = (uint16_t)(tsCalc / FOUR_YEARS_W_LJ),
tsCalc -= tsCalc / FOUR_YEARS_W_LJ * FOUR_YEARS_W_LJ,
leapQuad();
year = 1600 + 400 * y400 + 100 * y100 + 4 * y4 + y;
{
static uint64_t const monthOffsets[2][12 + 1] alignas(CL_SIZE) =
{
{ 0 * DAY, 31 * DAY, 59 * DAY, 90 * DAY, 120 * DAY, 151 * DAY, 181 *
DAY, 212 * DAY, 243 * DAY, 273 * DAY, 304 * DAY, 334 * DAY, 999 * DAY },
{ 0 * DAY, 31 * DAY, 60 * DAY, 91 * DAY, 121 * DAY, 152 * DAY, 182 *
DAY, 213 * DAY, 244 * DAY, 274 * DAY, 305 * DAY, 335 * DAY, 999 * DAY }
};
uint64_t const *pMonthOffsets = monthOffsets[isLeapYear];
size_t moHit;
if constexpr( !SYSTEM_TIME_BINARY_SEARCH )
for( moHit = 0; tsCalc >= pMonthOffsets[moHit + 1]; ++moHit );
else
{
size_t lower = 0, upper = 12, mid;
moHit = -1;
do
{
mid = (lower + upper) / 2;
if( pMonthOffsets[mid] <= tsCalc )
moHit = mid,
lower = mid + 1;
else
upper = mid;
} while( lower != upper );
assert( moHit != -1 );
}
uint64_t mo = pMonthOffsets[moHit];
uint8_t dy = (uint8_t)((tsCalc - mo) / DAY);
tsCalc -= mo + dy * DAY;
month = 1 + (uint8_t)moHit;
day = 1 + dy;
}
hour = (uint8_t)(tsCalc / HOUR);
tsCalc %= HOUR;
minute = (uint8_t)(tsCalc / MINUTE);
tsCalc %= MINUTE;
second = (uint8_t)(tsCalc / SECOND);
if( leapSecond ) [[unlikely]]
{
if( second != 59 || minute != 59 || hour != 23 || (month != 6 || day
!= 30) && (month != 12 || day != 31) ) [[unlikely]]
return reasonableErr( WRONG_LEAP_SECOND );
shared_ptr leapSeconds( g_leapSeconds.load( memory_order_relaxed ) );
size_t lower = 0, upper = leapSeconds->size();
for( ; ; )
{
size_t mid = (lower + upper) / 2;
leap_second_t const &ls = (*leapSeconds)[mid];
if( ls.year == year ) [[unlikely]]
if( month == 6 && ls.jun30 || month == 12 && ls.dec31 ) [[likely]]
{
++second;
break;
}
else
return reasonableErr( WRONG_LEAP_SECOND );
bool midIsLower = ls.year < year;
(midIsLower ? lower : upper) = mid + midIsLower;
if( lower == upper ) [[unlikely]]
return reasonableErr( WRONG_LEAP_SECOND );
}
}
tsCalc %= SECOND;
ns100 = (uint32_t)tsCalc;
}

// may throw date_error
// may throw system_error
// may throw bad_alloc

extern system_time::leap_second_t const leapSecondsInit2016[26];

st_timestamp system_time::to_timestamp( reason_t *reason ) const noexcept
{
using namespace std;
auto reasonableErr = [&]( reason_t retReason ) -> st_timestamp
{
if( reason ) [[likely]]
*reason = retReason;
return st_timestamp( -1 );
};
if( year < 1601 || year > 30828 ) [[unlikely]]
return reasonableErr( YEAR_OUT_OF_RANGE );
if( month < 1 || month > 12 ) [[unlikely]]
return reasonableErr( MONTH_OUT_OF_RANGE );
bool isLeapYear = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
static uint8_t const monthLengths[2][1 + 12] alignas(CL_SIZE) =
{
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
};
if( day == 0 || day > monthLengths[isLeapYear][month] ) [[unlikely]]
return reasonableErr( DAY_OUT_OF_RANGE );
if( hour >= 24 ) [[unlikely]]
return reasonableErr( HOUR_OUT_OF_RANGE );
if( minute >= 60 ) [[unlikely]]
return reasonableErr( MINUTE_OUT_OF_RANGE );
uint8_t sec = second;
uint64_t leapSecondBit = 0;
if( sec >= 60 ) [[unlikely]]
{
if( sec != 60 || minute != 59 || hour == 23 || (month != 6 || day !=
30) && (month != 12 || day != 31) ) [[unlikely]]
return reasonableErr( SECOND_OUT_OF_RANGE );
shared_ptr leapSeconds( g_leapSeconds.load( memory_order_relaxed ) );
if( !leapSeconds ) [[unlikely]]
{
size_t i = 0;
leap_seconds(
[&]( bool reset ) -> leap_second_t
{
i = !reset ? i : 0;
if( i != size( ::leapSecondsInit2016 ) ) [[likely]]
return ::leapSecondsInit2016[i++];
else
return leap_second_t { 0xFFFFu, false, false };
} );
leapSeconds = g_leapSeconds.load( memory_order_relaxed );
}
size_t lower = 0, upper = leapSeconds->size();
for( ; ; )
{
size_t mid = (lower + upper) / 2;
leap_second_t const &ls = (*leapSeconds)[mid];
if( ls.year == year ) [[unlikely]]
if( month == 6 && ls.jun30 || month == 12 && ls.dec31 ) [[likely]]
{
--sec, leapSecondBit = LEAP_SECOND_BIT;
break;
}
else
return reasonableErr( SECOND_OUT_OF_RANGE );
bool midIsLower = ls.year < year;
(midIsLower ? lower : upper) = mid + midIsLower;
if( lower == upper ) [[unlikely]]
return reasonableErr( SECOND_OUT_OF_RANGE );
}
}
if( ns100 >= 10'000'000 ) [[unlikely]]
return reasonableErr( NS100_OUT_OF_RANGE );
uint16_t yr = year - 1600;
uint64_t timestamp = yr / 400 * FOUR_HUNDRED_YEARS;
yr %= 400;
auto leapQuad = [&]()
{
timestamp += yr / 4 * FOUR_YEARS_W_LJ;
yr %= 4;
if( yr >= 1 ) [[likely]]
timestamp += LEAP_YEAR + (yr - 1) * NON_LEAP_YEAR;
};
if( yr >= 100 ) [[likely]]
{
timestamp += FIRST_QUARTER_CENTURY;
yr -= 100;
timestamp += yr / 100 * REMAINING_QUARTER_CENUTRIES;
yr %= 100;
if( yr >= 4 ) [[likely]]
timestamp += FOUR_YEARS_WO_LJ,
yr -= 4,
leapQuad();
else
timestamp += yr * NON_LEAP_YEAR;
}
else
leapQuad();
timestamp -= LEAP_YEAR; // - (1.1.1601 - 1.1.1600)
static uint16_t const monthOffsets[2][1 + 12] alignas(CL_SIZE) =
{
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
};
timestamp += (monthOffsets[isLeapYear][month] + day - 1) * DAY;
timestamp += hour * HOUR;
timestamp += minute * MINUTE;
timestamp += sec * SECOND;
timestamp += ns100;
if( timestamp > (uint64_t)numeric_limits<int64_t>::max() ) [[unlikely]]
return reasonableErr( TIMESTAMP_BEYOND_63_BIT );
if( reason ) [[likely]]
*reason = (reason_t)0;
return timestamp | leapSecondBit;
}

// may throw date_error

system_time::operator st_timestamp() const
{
reason_t reason;
st_timestamp ts = to_timestamp( &reason );
if( reason ) [[unlikely]]
throw date_error( reason );
return ts;
}

#if defined(_MSC_VER)
// may throw date_error

system_time::operator SYSTEMTIME() const
{
reason_t reason;
SYSTEMTIME st = to_systemtime( &reason );
if( reason ) [[unlikely]]
throw date_error( reason );
return st;
}

SYSTEMTIME system_time::to_systemtime( reason_t *reason ) const noexcept
{
SYSTEMTIME st;
st.wYear = year;
st.wDay = day;
st.wHour = hour;
st.wMinute = minute;
st.wSecond = second;
st.wMilliseconds = (WORD)(ns100 / 10'000);
reason_t lReason;
st_timestamp timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = lReason;
memset( &st, 0, sizeof st );
return st;
}
st.wDayOfWeek = get_weekday( timestamp );;
return st;
}

// may throw date_error

system_time &system_time::operator =( SYSTEMTIME const &st )
{
reason_t reason;
from_systemtime( st, &reason );
if( reason ) [[unlikely]]
throw date_error( reason );
return *this;
}

bool system_time::from_systemtime( SYSTEMTIME const &st, reason_t
*reason ) noexcept
{
system_time stAux;
stAux.year = st.wYear;
stAux.month = (uint8_t)st.wMonth;
stAux.day = (uint8_t)st.wDay;
stAux.hour = (uint8_t)st.wHour;
stAux.minute = (uint8_t)st.wMinute;
stAux.second = (uint8_t)st.wSecond;
stAux.ns100 = (uint32_t)st.wMilliseconds * 10'000;
reason_t lReason;
st_timestamp timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = lReason;
return false;
}
stAux.weekday = get_weekday( timestamp );
*this = stAux;
return true;
}

#endif

// may throw date_error

system_time::operator tm() const
{
reason_t reason;
struct tm tm( to_tm( &reason ) );
if( reason ) [[unlikely]]
throw date_error( reason );
return tm;
}

struct tm system_time::to_tm( reason_t *reason ) const noexcept
{
using namespace std;
auto reasonableErr = [&]( reason_t retReason ) -> struct tm
{
if( reason ) [[likely]]
*reason = retReason;
return tm( -1 );
};
if( year < 1900 || year - 1900u > (unsigned)numeric_limits<int>::max()
) [[unlikely]]
return reasonableErr( YEAR_OUT_OF_RANGE );
reason_t lReason;
uint64_t timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
return reasonableErr( lReason );
uint8_t wd = get_weekday( timestamp );
struct tm tm;
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
uint16_t const monthOffsets[2][1 + 12] alignas(CL_SIZE) =
{
{ 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
{ 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
};
tm.tm_yday = monthOffsets[year % 4 == 0 && year % 100 != 0 || year %
400 == 0][month] + day - 1;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
tm.tm_wday = wd;
return tm;
}

// may throw date_error

system_time &system_time::operator =( struct tm const &tm )
{
reason_t reason;
if( !from_tm( tm, &reason ) ) [[unlikely]]
throw date_error( reason );
return *this;
}

bool system_time::from_tm( struct tm const &tm, reason_t *reason ) noexcept
{
auto reasonableErr = [&]( reason_t retReason ) -> bool
{
if( reason ) [[unlikely]]
*reason = retReason;
return false;
};
if( tm.tm_year < 1601 - 1900 || tm.tm_year > 30828 - 1900 ) [[unlikely]]
return reasonableErr( YEAR_OUT_OF_RANGE );
system_time stAux;
stAux.year = tm.tm_year + 1900;
stAux.month = tm.tm_mon + 1;
stAux.day = tm.tm_mday;
stAux.hour = tm.tm_hour;
stAux.minute = tm.tm_min;
stAux.second = tm.tm_sec;
stAux.ns100 = 0;
reason_t lReason;
uint64_t timestamp = stAux.to_timestamp( &lReason );
if( lReason ) [[unlikely]]
return reasonableErr( lReason );
stAux.weekday = get_weekday( timestamp );
*this = stAux;
return true;
}

// may throw date_error

time_t system_time::timestamp_to_time_t( st_timestamp ts, reason_t
*reason ) noexcept
{
if( (uint64_t)ts < TIME_T_IN_TIMESTAMP_BEGIN ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = TIMESTAMP_BEFORE_TIME_T;
return -1;
}
return ((uint64_t)ts - TIME_T_IN_TIMESTAMP_BEGIN) / SECOND;
}

// may throw date_error

st_timestamp system_time::time_t_to_timestamp( time_t time, reason_t
*reason ) noexcept
{
if( time > LAST_TIMESTAMP_IN_TIME_T ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = TIMESTAMP_BEYOND_63_BIT;
return -1;
}
return st_timestamp( TIME_T_IN_TIMESTAMP_BEGIN + time * SECOND );
}

// may throw date_error

inline bool system_time::adjust_weekday( reason_t *reason ) noexcept
{
reason_t lReason;
uint64_t timestamp = to_timestamp( &lReason );
if( lReason ) [[unlikely]]
{
if( reason ) [[likely]]
*reason = lReason;
return false;
}
weekday = get_weekday( timestamp );
return true;
}

system_time::date_error::date_error( reason_t reason ) :
invalid_argument(
[]( reason_t reason ) -> char const *
{
static struct err_map_t
{
reason_t reason;
char const *what;
} const errMaps[] =
{
err_map_t { TIMESTAMP_BEYOND_63_BIT, "system_time - timestamp beyond
63 bit (14.9.30828 22:48:5.4775807)" },
err_map_t { YEAR_OUT_OF_RANGE, "system_time - year out of range" },
err_map_t { MONTH_OUT_OF_RANGE, "system_time - month out of range" },
err_map_t { DAY_OUT_OF_RANGE, "system_time - day out of range" },
err_map_t { HOUR_OUT_OF_RANGE, "system_time - hour out of range" },
err_map_t { MINUTE_OUT_OF_RANGE, "system_time - minute out of range" },
err_map_t { SECOND_OUT_OF_RANGE, "system_time - second out of range" },
err_map_t { NS100_OUT_OF_RANGE, "system_time - 100ns-steps out of
range" },
err_map_t { TIMESTAMP_BEFORE_TIME_T, "system_time - timestamp before
time_t (1.1.1970 00:00.0)" }
};
for( err_map_t const &errMap : errMaps )
if( errMap.reason == reason ) [[unlikely]]
return errMap.what;
return "";
}( reason ) ),
m_reason( reason )
{
}

// may throw bad_alloc
// may throw invalid_argument if there's a duplicate leap year from the
feeder
// may throw date_error if a year is out of range (< 1601 || > 30828)
// may throw invalid_argument if leap year from feeder has no leaps

void system_time::leap_seconds( std::function<leap_second_t ( bool )>
const &feeder )
{
using namespace std;
auto feedLoop = [&]<typename Fn>( Fn fn ) -> size_t
requires requires( Fn fn, leap_second_t const &ls ) { { fn( ls ) }; }
{
size_t i = 0;
for( leap_second_t ls; (ls = feeder( i++ == 0 )).year != 0xFFFFu; fn(
ls ) );
return i;
};
vector<leap_second_t> leaps;
leaps.reserve( feedLoop( [&]( leap_second_t const & ) { } ) );
feedLoop( [&]( leap_second_t const &ls ) { leaps.emplace_back( ls ); } );
sort( leaps.begin(), leaps.end(),
[]( leap_second_t &lhs, leap_second_t &rhs ) -> bool { return lhs.year
< rhs.year; } );
for( leap_second_t const &lp : leaps )
if( &lp != &leaps[0] && lp.year == (&lp)[-1].year ) [[unlikely]]
throw invalid_argument( "duplicate leap year" );
else if( lp.year < 1601 || lp.year > 30828 ) [[unlikely]]
throw date_error( YEAR_OUT_OF_RANGE );
else if( !lp.jun30 && !lp.dec31 ) [[unlikely]]
throw invalid_argument( "leap year without leaps" );
g_leapSeconds.store( make_shared<vector<leap_second_t>>( move( leaps )
), memory_order_release );
}

atomic<shared_ptr<vector<system_time::leap_second_t>>>
system_time::g_leapSeconds;

static system_time::leap_second_t const leapSecondsInit2016[26] =
{
{ 1972, true, true },
{ 1973, false, true },
{ 1974, false, true },
{ 1975, false, true },
{ 1976, false, true },
{ 1977, false, true },
{ 1978, false, true },
{ 1979, false, true },
{ 1981, true, false },
{ 1982, true, false },
{ 1983, true, false },
{ 1985, true, false },
{ 1987, false, true },
{ 1989, false, true },
{ 1990, false, true },
{ 1992, true, false },
{ 1993, true, false },
{ 1994, true, false },
{ 1995, false, true },
{ 1997, true, false },
{ 1998, false, true },
{ 2005, false, true },
{ 2008, false, true },
{ 2012, true, false },
{ 2015, true, false },
{ 2016, false, true }
};

This is similar to Windows' FILETIME (100ns-intervals since 1.1.1601
00:00:00.0) and you can convert the C-timestamps also to st_timestamp.
st_timestamp is a 64 bit timestamp which uses the highes bit to indi-
cate if the timestamp is within a leap-second. If you - implicitly
or explicitly - convert the st_timestamp to an uint64_t the highest
bit is stripped and you can calculate with it like with a Unix-time-
stamp, but with a higher resolution. You can implicitly or explicitly
convert back an uint64_t-value to a st_timestamp independently on if
the highest bit is set or not. The bit is only honored if you convert
this timestamp to a system_time object, i.e. the second-part is set
to 60 if the st_timestamp corresponds to a legal leap-second.

Ben Bacarisse

unread,
Nov 4, 2022, 3:51:01 PM11/4/22
to
Have you ruled out tmpnam and tmpfile?

--
Ben.

Lynn McGuire

unread,
Nov 4, 2022, 4:16:25 PM11/4/22
to
I just ported this code from F77 to C++. I totally forgot about tmpnam
and tmpfile.

Thanks,
Lynn

Keith Thompson

unread,
Nov 4, 2022, 6:05:56 PM11/4/22
to
An alternative is to keep a counter, incremented for each generated file
name, and append it to the file name, perhaps resetting to 0 when the
seconds count advances. If your only requirement is uniqueness, that
should be good enough.

Digression: I remember an implementation of gettimeofday() that did
something like that (on SunOS, maybe?). The system clock had a
resolution of 0.01 second, so the value of tv_usec on successive calls
might be:
420000
420001
420002
430000
430001
430002
...
I don't remember whether the implicit counter was per-process or
system-wide.

Lynn McGuire

unread,
Nov 4, 2022, 6:35:30 PM11/4/22
to
The problem is multiple instances of the same program creating the same
name files.

Lynn

Chris M. Thomasson

unread,
Nov 4, 2022, 6:56:34 PM11/4/22
to
Prepend the file names with the PID? Something to make it unique.
Perhaps a SHA2-HMAC or something.

Keith Thompson

unread,
Nov 4, 2022, 7:16:05 PM11/4/22
to
You could incorporate the process id into the file name.

There's no truly portable way to do that, but one solution for POSIX and
another for Windows is likely to be good enough.

Opus

unread,
Nov 6, 2022, 2:54:11 PM11/6/22
to
Le 04/11/2022 à 06:06, Lynn McGuire a écrit :
> I forgot to add I would prefer a portable way if possible.  I suspect
> that is not possible though below the second resolution.

You're asking specifically on Windows, and then you now want a portable
solution. There isn't. But you could write your own compatibility layer,
calling either Windows API functions or POSIX functions. This isn't
rocket science. I've done that long ago and keep reusing it. There may
of course be many third-party code/libraries doing just that if you
don't want to do it yourself.

IME, using performance counters on Windows is the only sure way of
getting proper resolution. Any third-party code will use them in one way
or another. Why not do that yourself, it'll be only a few lines of code
to write a compatibility layer.

Michael S

unread,
Nov 6, 2022, 5:30:22 PM11/6/22
to
Why do it it yourself?
I don't find it very likely that compatibility layer consisting of few lines
of code written by non-specialist will do a better job than compatibility
layer provided by standard C++ library, in particular one in
std::chrono::stable_clock.

Michael S

unread,
Nov 6, 2022, 5:42:06 PM11/6/22
to
If you decided to keep ideas of your old code* then using __rdtsc() is hand
down better than anything else. Of course, don't convert result of
__rdtsc() to microseconds, use the number in its entirety. This way you still
would not get 100% guarantee against name conflicts between multiple
instances, but probability of conflict will be 3-6 orders of magnitude lower
than any other time-based method.
------------
* - IMHO, you should not. Posters here suggested at least two better solutions
and can suggest more. BTW, are you sure that with modern memory
capacity you still need temporary files at all?

Alf P. Steinbach

unread,
Nov 7, 2022, 1:48:43 AM11/7/22
to
But here your belief is in direct conflict with reality.

The MinGW g++ chrono implementation has had (and probably still has) a
dynamically varying resolution down to 1/30 second, extremely unusable.

- Alf


Juha Nieminen

unread,
Nov 7, 2022, 2:21:15 AM11/7/22
to
Öö Tiib <oot...@hot.ee> wrote:
> I have such code snippet copy-pasted from somewhere about portable
> since C++11.
>
> auto t0 = std::chrono::high_resolution_clock::now();
> auto nanosec = t0.time_since_epoch();
>
> std::cout << nanosec.count() << " nanoseconds since epoch\n";
> std::cout << nanosec.count() / (1000000000.0 * 60.0 * 60.0) << " hours since epoch\n";
>
> As I rarely need nanoseconds haven't tried it everywhere
> but at least looks portable.

I highly doubt that's going to return values at the nanosecond, or even
microsecond accuracy. (In other words, it's likely that the returned
value will jump by significantly more than a microsecond, at larger
time intervals, meaning that if you read the time again within that
time interval you'll just get the same value.)

Although, of course, this will depend on the target platform.
At a very minimum you can't assume the return value will have that
resolution.

(I don't know what guarantees the standard gives for this. Probably
none.)

Michael S

unread,
Nov 7, 2022, 7:11:38 AM11/7/22
to
MinGW is obsolete since long ago, close to 10 years.
It is replaced by MSYS2/Mingw64.
Mingw64 had (has?) various problems with implementations of
std::chrono::high_resolution_clock and, may be (not sure)
of std::chrono::system_clock. But I don't suggest any of those.
I suggest std::chrono::steady_clock. It has reasonable
implementations on all x86-64 systems that I ever tested.

Anyway, it seems to me that OPs attitude is toward using
the most popular C++ tools on any given platform, i.e. MSVC on
Windows, LLVM/clang (via Xcode) on Mac and gcc on Linux.
Portability to more exotic tools+OS combinations is not required.

Scott Lurndal

unread,
Nov 7, 2022, 9:39:42 AM11/7/22
to
If you are using the RDTSC instruction, be aware that the value returned
may vary based on the current clock speed; there are some chips where the
frequency of the clock RDTSC returns is invariant, others not so much.

https://stackoverflow.com/questions/4509727/how-to-detect-if-rdtsc-returns-a-constant-rate-counter-value

Öö Tiib

unread,
Nov 7, 2022, 10:11:25 AM11/7/22
to
On Monday, 7 November 2022 at 09:21:15 UTC+2, Juha Nieminen wrote:
> Öö Tiib <oot...@hot.ee> wrote:
> > I have such code snippet copy-pasted from somewhere about portable
> > since C++11.
> >
> > auto t0 = std::chrono::high_resolution_clock::now();
> > auto nanosec = t0.time_since_epoch();
> >
> > std::cout << nanosec.count() << " nanoseconds since epoch\n";
> > std::cout << nanosec.count() / (1000000000.0 * 60.0 * 60.0) << " hours since epoch\n";
> >
> > As I rarely need nanoseconds haven't tried it everywhere
> > but at least looks portable.
>
> I highly doubt that's going to return values at the nanosecond, or even
> microsecond accuracy. (In other words, it's likely that the returned
> value will jump by significantly more than a microsecond, at larger
> time intervals, meaning that if you read the time again within that
> time interval you'll just get the same value.)

In some places it will work well enough for some use cases:
<http://coliru.stacked-crooked.com/a/a911aa914ed22a56>
As the calls themselves seem to take a microsecond that
resolution does not matter indeed.

> Although, of course, this will depend on the target platform.
> At a very minimum you can't assume the return value will have that
> resolution.

Anything can be not good enough for our case on some platform.
When I tried it worked well enough for what I needed in some places.

> (I don't know what guarantees the standard gives for this. Probably
> none.)

It does not matter as even when standard will give very good guarantees
then some of Microsoft, Apple, Intel, IBM, Google, Oracle, Texas
Instruments and what are they will anyway ensure that it does do
something odd on their platform or with third party compiler on their
platform or with their compiler on platform of someone else. The
engineers of those do not report to standard but to their peers who
report to shareholders.

It has been same all those decades.

Michael S

unread,
Nov 7, 2022, 2:03:58 PM11/7/22
to
OP appears to wants unique number rather than real microseconds.

In today's x86 word RDTSC is based of "official frequency" of
given CPU model and is not related to actual current clock speed.
It was not universally so up until mid-00s, but we are in 2022.
But all that irrelevant for specific use case.

Lynn McGuire

unread,
Nov 8, 2022, 12:27:16 AM11/8/22
to
Port to C++ first then improve. Improving inside the porting loop can
bring in all kinds of bugs. A couple of the temporary files are related
to our inline Fortran interpreter that the users use to add in their own
custom calculations. There is some serious juju going on there.

Thanks,
Lynn

Alf P. Steinbach

unread,
Nov 8, 2022, 12:30:32 PM11/8/22
to
Oh my. I just don't care to write MinGW64, it's a bit of a mouthful and
in general very unnecessary. Most people understand.

But to be precise you're comparing the compiler/tool project MinGW with
the compiler distribution and Unix-like eco-system MSYS2. MSYS2 provides
one distro of MinGW64. Nuwen (that's STL at Microsoft, or if you like,
prince Nuwen from the Vernor Vinge novels) another. There are others.

The project that provides the basic sources that they all use is the
MingW64 project, <url: https://www.mingw-w64.org/>.


> Mingw64 had (has?) various problems with implementations of
> std::chrono::high_resolution_clock and, may be (not sure)
> of std::chrono::system_clock. But I don't suggest any of those.
> I suggest std::chrono::steady_clock. It has reasonable
> implementations on all x86-64 systems that I ever tested.

The MinGW (that is, MinGW64) g++ implementation was not reasonable, and
probably isn't today either.

>
> Anyway, it seems to me that OPs attitude is toward using
> the most popular C++ tools on any given platform, i.e. MSVC on
> Windows, LLVM/clang (via Xcode) on Mac and gcc on Linux.
> Portability to more exotic tools+OS combinations is not required.

Portable code is often, and in this case would be, /less/ code.

As such it is more likely correct code.

The problem is when a C++ implementation doesn't manage to provide the
implied usability guarantee. It's sort of like a C++ implementation with
a 1 MB `bool`, so that you can't have two of them on a default machine
stack. That's formally OK; it just fails to provide a /usable/ `bool`.

- Alf

PS: I'm sorry that I by mistake sent essentially this reply via mail,
presumably to an unused spam-dump e-mail address, but. Not sure how
Thunderbird managed to trick me into doing that.

Michael S

unread,
Nov 8, 2022, 6:37:23 PM11/8/22
to
IMO, you are confused.
From the very beginning mingw64 std::chrono::steady_clock() is based on
QueryPerformanceCounter().
It's not the best possible clock available on Windows, but certainly not broken.
It has sub-microsecond resolution. Typically ~331ns.

Most likely you had seen std::chrono::high_resolution_clock broken (and
this one is broken indeed) and remembered that *something* is broken,
but forgot what is broken and what not.

> >
> > Anyway, it seems to me that OPs attitude is toward using
> > the most popular C++ tools on any given platform, i.e. MSVC on
> > Windows, LLVM/clang (via Xcode) on Mac and gcc on Linux.
> > Portability to more exotic tools+OS combinations is not required.
> Portable code is often, and in this case would be, /less/ code.
>
> As such it is more likely correct code.
>
> The problem is when a C++ implementation doesn't manage to provide the
> implied usability guarantee. It's sort of like a C++ implementation with
> a 1 MB `bool`, so that you can't have two of them on a default machine
> stack. That's formally OK; it just fails to provide a /usable/ `bool`.
>
> - Alf
>
> PS: I'm sorry that I by mistake sent essentially this reply via mail,
> presumably to an unused spam-dump e-mail address, but. Not sure how
> Thunderbird managed to trick me into doing that.

That's o.k.
This mail address is not totally unused, but it is used may be once or
twice per year.

Öö Tiib

unread,
Nov 9, 2022, 9:15:05 AM11/9/22
to
From that steady_clock we are supposed to get time since arbitrary time
point of past. No years and months that OP had. That is useful only in
context of checking durations of works or time-ordering of events of
(threads of) current process. If used as (parts of) file names (like OP
seemed to want) the ordering and time distances become wrong with
restart of system.

Michael S

unread,
Nov 12, 2022, 7:21:15 PM11/12/22
to
Elaboration and rectification:
Mingw64 std::chrono::high_resolution_clock is broken on Win7 and derivatives
like WS2008r2.
On Window 10 and derivatives (WS2016 and Ws2019) it works fine.
In particular, on the Ws2019 it works not just fine, but very well providing
100ns increments.

Lynn McGuire

unread,
Nov 14, 2022, 5:59:03 PM11/14/22
to
On 11/4/2022 8:44 AM, Scott Lurndal wrote:
> Lynn McGuire <lynnmc...@gmail.com> writes:
>> What is the best way to get microseconds of time on Windows in C or C++
>> ? I am currently using the following code to get the current time:
>>
>> std::time_t t = std::time (0); // get time now
>> std::tm * now = std::localtime ( & t);
>> integer iyear = now -> tm_year + 1900;
>> integer imonth = now -> tm_mon + 1;
>> integer iday = now -> tm_mday;
>> integer ihour = now -> tm_hour;
>> integer imin = now -> tm_min;
>> integer isec = now -> tm_sec;
>> integer ihund = 0;
>>
>> Thanks,
>> Lynn
>
"Nowadys I would use the following for gettimeofday() on Windows, which
is using GetSystemTimePreciseAsFileTime() if compiled for Windows 8 or
higher and GetSystemTimeAsFileTime() otherwise:"

I used the gettimeofday function. Works well !

Thanks,
Lynn

Keith Thompson

unread,
Nov 14, 2022, 8:36:47 PM11/14/22
to
Be aware that POSIX says gettimeofday() is obsolescent, and recommends
clock_gettime() instead.

Lynn McGuire

unread,
Nov 15, 2022, 6:26:31 PM11/15/22
to
This works fine for me:

// from:
//
https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows

struct timezone {
int tz_minuteswest;
int tz_dsttime;
};

int mygettimeofday (struct timeval *tv, struct timezone *tz)
{
if (tv) {
FILETIME filetime; /* 64-bit value representing the
number of 100-nanosecond intervals since January 1, 1601 00:00 UTC */
ULARGE_INTEGER x;
ULONGLONG usec;
static const ULONGLONG epoch_offset_us = 11644473600000000ULL; /*
microseconds betweeen Jan 1,1601 and Jan 1,1970 */

#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
GetSystemTimePreciseAsFileTime ( & filetime);
#else
GetSystemTimeAsFileTime ( & filetime);
#endif
x.LowPart = filetime.dwLowDateTime;
x.HighPart = filetime.dwHighDateTime;
usec = x.QuadPart / 10 - epoch_offset_us;
tv->tv_sec = (time_t) (usec / 1000000ULL);
tv->tv_usec = (long) (usec % 1000000ULL);
}
if (tz) {
TIME_ZONE_INFORMATION timezone;
GetTimeZoneInformation(&timezone);
tz->tz_minuteswest = timezone.Bias;
tz->tz_dsttime = 0;
}
return 0;
}

Thanks,
Lynn

Andreas

unread,
Nov 16, 2022, 7:15:18 AM11/16/22
to
Am 16.11.2022 um 00:26 schrieb Lynn McGuire:
> This works fine for me:
>
>     //  from:
>     //
> https://stackoverflow.com/questions/10905892/equivalent-of-gettimeday-for-windows
>
> struct timezone {
>     int tz_minuteswest;
>     int tz_dsttime;
> };
>
> int mygettimeofday (struct timeval *tv, struct timezone *tz)
> {
>     if (tv) {
>         FILETIME               filetime; /* 64-bit value representing
> the number of 100-nanosecond intervals since January 1, 1601 00:00 UTC */
>         ULARGE_INTEGER         x;
>         ULONGLONG              usec;
>         static const ULONGLONG epoch_offset_us = 11644473600000000ULL;
Wrong value. Correct value is 116444736000000000ULL (9 trailing zeros).

Rough estimation (1970-1601)*365*24*60*60 = 11'636'784'000 seconds
(ignoring Feb 29 in leap years). Additional 6 zeros to convert seconds
to microseconds.

Manu Raju

unread,
Nov 20, 2022, 4:39:36 PM11/20/22
to
On 04/11/2022 01:14, Lynn McGuire wrote:
> What is the best way to get microseconds of time on Windows in C or
> C++ ?  I am currently using the following code to get the current time:
>
>     std::time_t t = std::time (0);   // get time now
>     std::tm * now = std::localtime ( & t);
>     integer iyear = now -> tm_year + 1900;
>     integer imonth = now -> tm_mon + 1;
>     integer iday = now -> tm_mday;
>     integer ihour = now -> tm_hour;
>     integer imin = now -> tm_min;
>     integer isec = now -> tm_sec;
>     integer ihund = 0;
>
> Thanks,
> Lynn

In c# I can use this code and it works:

DateTime test = DateTime.Now;

Console.WriteLine($"Day: {test.Day}");
Console.WriteLine($"Month: {test.Month}");
Console.WriteLine($"Year: {test.Year}");
Console.WriteLine($"Hour: {test.Hour}");
Console.WriteLine($"Minute: {test.Minute}");
Console.WriteLine($"Second: {test.Second}");
Console.WriteLine($"Microseconds: {test.Microsecond}");
Console.WriteLine($"Nanoseconds: {test.Nanosecond}");
Console.WriteLine($"Ticks: {test.Ticks}");



0 new messages