views:

1182

answers:

1

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.

  1. Is my algorithm flawed somehow? Does anyone see anything obvious that I've missed? Are there boundary conditions where this won't work right?
  2. Is there a better way to do the conversion? Does .NET have a way to do this in a more straightforward manner?
A: 

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.

Hans Passant
Not so worried about Y2K38. :) What do you mean regarding the cleverness of dateTime.Millisecond?
Matt Davis