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
_tzsetfor 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?
You’re aware of the Y2K38 problem? I assume you checked the sign of .timezone. Avoid the cleverness of using dateTime.Millisecond, that just confuses the next guy. Looks good otherwise.