I have a legacy C++-based application that timestamps incoming network traffic using the CRT _ftime()
function. The _ftime()
function returns a _timeb
structure, which has a 32-bit and a 64-bit implementation. We are using the 32-bit implementation, which looks like this:
struct _timeb {
long time; // 4 bytes
unsigned short millitm; // 2 bytes
short timezone; // 2 bytes
short dstflag; // 2 bytes
};
From the MSDN documentation, here is how each field is interpreted:
- dstflag - nonzero if daylight savings time is currently in effect for the local time zone (see
_tzset
for an explanation of how daylight savings time is determined.) - millitm - fraction of a second in milliseconds
- time - time in seconds since midnight (00:00:00), January 1, 1970, coordinated universal time (UTC).
- timezone - difference in minutes, moving westward, between UTC and local time. The value of timezone is set from the value of the global variable
_timezone
(see_tzset
).
I am re-working the portion of the code that does the timestamping to use C# in .NET 3.5. Timestamps are now generated using the System.DateTime
structure, but I still need to convert them back to the _timeb
structure so the legacy C++ code can operate on them. Here is how I am doing that in my managed C++ bridge library:
DateTime dateTime = DateTime::UtcNow;
DateTime baseTime(1970, 1, 1, 0, 0, 0, DateTimeKind::Utc);
TimeSpan delta = dateTime - baseTime;
_timeb timestamp;
timestamp.time = delta.TotalSeconds;
timestamp.millitm = dateTime.Millisecond;
timestamp.dstflag = TimeZoneInfo::Local->IsDaylightSavingTime(dateTime) ? 1 : 0;
timestamp.timezone = TimeZoneInfo::Local->BaseUtcOffset.TotalMinutes * -1;
From what I can tell, this appears to reconstruct the _timeb
structure as if I had called _ftime()
directly, and that's good. The thing is, timestamps are a critical piece of our application, so this has to be right.
My question is two-fold.
- Is my algorithm flawed somehow? Does anyone see anything obvious that I've missed? Are there boundary conditions where this won't work right?
- Is there a better way to do the conversion? Does .NET have a way to do this in a more straightforward manner?