Я конвертирую некоторый код С++ в С#. Я не могу воспроизвести эквивалентные значения при преобразовании из структуры tm и mktime() в С#.
Пример: Обе версии используют одни и те же значения:
int year = 2022;
int month = 9;
int day = 5;
int hour = 0;
int minute = 27;
int second = 20;
В С++:
struct tm sampleTime;
unsigned long longTime;
sampleTime.tm_year = year;
sampleTime.tm_mon = month - 1;
sampleTime.tm_mday = day;
sampleTime.tm_hour = hour;
sampleTime.tm_min = minute;
sampleTime.tm_sec = second;
sampleTime.tm_wday = 0;
sampleTime.tm_yday = 0;
sampleTime.tm_isdst= 0;
longTime = mktime(&thistime);
Значение longTime равно 1662366439.
В С#:
DateTime sampleTime = new DateTime(year, month, day, hour, minute, second);
DateTime unixEpoch = new DateTime(1970, 1, 1);
ulong longTime = (ulong)(sampleTime - unixEpoch).TotalSeconds;
Значение longTime равно 1662337639.
Так что они очень близки, но расходятся, и мне нужно, чтобы они были эквивалентны. Что мне здесь не хватает?
@PaulMcKenzie Я слышу вас, но значения должны совпадать, потому что они используются в вычислениях и сохраняют значения давным-давно (до тех пор, пока их нельзя будет обновить).
C# использует .NET для своих целей, а C++ — нет. Вы пытаетесь заставить две совершенно разные вещи иметь одинаковую ценность, и ни одна из них не находится под вашим контролем. Кроме того, предположим, что вы получили несколько совпадающих значений — что вы будете делать, когда получите сообщение об ошибке, в котором какое-то нечетное значение из тысяч не совпадает? Это может быть проигрышная игра, пытающаяся исправить эту «ошибку» только для того, чтобы внести ошибку где-то еще.
Разница 8 часов. Это наводит меня на мысль, что причина в учете часовых поясов или нет.





mktime() принимает tm, выраженное в местном времени, тогда как эпоха Unix вместо этого выражается во времени UTC.
Конструкторы C# DateTime(), которые вы вызываете, не знают, относятся ли указанные значения даты/времени к местному времени или времени UTC, поэтому свойство Kind результирующих DateTimes равно Unspecified, что может вызвать ошибки вычислений. Итак, вам нужно использовать другие конструкторы DateTime, которые делают каждый Kind явным, чтобы при необходимости можно было вносить коррективы во время вычислений, например:
DateTime sampleTime = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Local);
DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
При этом обратите внимание, что код C++ устанавливает sampleTime.tm_isdst = 0, чтобы указать, что указанная дата/время НЕ находится в летнее время, даже если реальная дата/время на самом деле находится в летнее время.
Я не уверен, как справиться с этим на стороне С#. Вам, вероятно, придется посмотреть, действительно ли указанный sampleTime находится в DST (то есть, через TimeZoneInfo.Local.IsDaylightSavingTime()), и если да, то отрегулируйте его соответствующим образом, чтобы вывести его из летнего времени, прежде чем выполнять дальнейшие вычисления с ним, например:
DateTime sampleTime = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Local);
DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeZoneInfo tz = TimeZoneInfo.Local;
if (tz.SupportsDaylightSavingTime && if tz.IsDaylightSavingTime(sampleTime))
{
// figure out the difference between Standard/Daylight times
// for this timezone at the specified date/time and adjust
// sampleTime accordingly ...
}
Я думаю, что вы правы насчет летнего времени, не уловил. Не уверен, как бы я его отрегулировал, но я буду возиться с этим. Спасибо!
Забудьте о существовании C++ и реализуйте дату и время в соответствии с лучшими практиками C#. Не пытайтесь «перевести» то, что C++ делает в C#, выполняя построчный перевод. Я уверен, что у C# есть способ сделать это, независимо от того, как это делает C++.