user2919933
user2919933

Reputation: 13

Implementing in C# the same behavior of CTime.GetTime() method

I'm trying to implement in C# the behavior of CTime::GetTime() method.

Here there is a code snippet of my console application (written in C++/CLI):

int main(array<System::String ^> ^args)
{
 int epochYear = 1970;
 int epochMonth = 1;
 int epochDay = 1;

 DateTime managedEpochDate = DateTime(epochYear, epochMonth, epochDay);

 int year = 2013;
 int month = 2;
 int day = 13;
 int hour = 9;
 int minutes = 49;
 int seconds = 46;

 // DateTime/CTime -> Numeric Time (__time64_t)

 DateTime managedDateTime = DateTime(year, month, day, hour, minutes, seconds);
 CTime nativeDateTime = CTime(year, month, day, hour, minutes, seconds);

 DWORD nativeTimeToSerialize = nativeDateTime.GetTime();
 UInt32 managedTimeToSerialize = (managedDateTime - managedEpochDate)
     .TotalSeconds;
}

At the end I have the following different values:

Can anyone help me to understand the why of this difference?

Upvotes: 1

Views: 1002

Answers (1)

BartoszKP
BartoszKP

Reputation: 35891

The difference comes from the fact that CTime constructor you're using converts the time to UTC:

This constructor makes the appropriate conversion to UTC.

Whereas the DateTime contructor (and the other one) is timezone unaware in this case:

The Kind property is initialized to DateTimeKind.Unspecified.

The subtraction operator of DateTime also doesn't take timezones into account:

The Subtraction(DateTime, DateTime) method does not consider the value of the Kind property of the two DateTime values when performing the subtraction.

To get the desired result set the last parameter for the CTime constructor appropriately, e.g.:

CTime nativeDateTime = CTime(year, month, day, hour, minutes, seconds, 0);

For modifying DateTime usages instead you need to have:

int epochYear = 1970;
int epochMonth = 1;
int epochDay = 1;

DateTime managedEpochDateUtc
    = new DateTime(epochYear, epochMonth, epochDay, 0, 0, 0, DateTimeKind.Utc);

int year = 2013;
int month = 2;
int day = 13;
int hour = 9;
int minutes = 49;
int seconds = 46;

DateTime managedDateTimeLocal
    = new DateTime(year, month, day, hour, minutes, seconds, DateTimeKind.Local);

DateTime managedDateTimeUtc = managedDateTimeLocal.ToUniversalTime();

uint managedTimeToSerialize = (uint)(managedDateTimeUtc - managedEpochDateUtc)
 .TotalSeconds;

Or, as suggested by Mgetz you can use DateTimeOffset instead of DateTime, which is generally recommended because DateTime doesn't handle timezones very clearly.

Upvotes: 1

Related Questions