Преобразование структуры c++ tm и mktime в C#

Я конвертирую некоторый код С++ в С#. Я не могу воспроизвести эквивалентные значения при преобразовании из структуры 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.

Так что они очень близки, но расходятся, и мне нужно, чтобы они были эквивалентны. Что мне здесь не хватает?

Забудьте о существовании C++ и реализуйте дату и время в соответствии с лучшими практиками C#. Не пытайтесь «перевести» то, что C++ делает в C#, выполняя построчный перевод. Я уверен, что у C# есть способ сделать это, независимо от того, как это делает C++.

PaulMcKenzie 01.05.2023 20:14

@PaulMcKenzie Я слышу вас, но значения должны совпадать, потому что они используются в вычислениях и сохраняют значения давным-давно (до тех пор, пока их нельзя будет обновить).

pfinferno 01.05.2023 20:16

C# использует .NET для своих целей, а C++ — нет. Вы пытаетесь заставить две совершенно разные вещи иметь одинаковую ценность, и ни одна из них не находится под вашим контролем. Кроме того, предположим, что вы получили несколько совпадающих значений — что вы будете делать, когда получите сообщение об ошибке, в котором какое-то нечетное значение из тысяч не совпадает? Это может быть проигрышная игра, пытающаяся исправить эту «ошибку» только для того, чтобы внести ошибку где-то еще.

PaulMcKenzie 01.05.2023 20:18

Разница 8 часов. Это наводит меня на мысль, что причина в учете часовых поясов или нет.

Avi Berger 01.05.2023 20:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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 ...
}

Я думаю, что вы правы насчет летнего времени, не уловил. Не уверен, как бы я его отрегулировал, но я буду возиться с этим. Спасибо!

pfinferno 01.05.2023 21:15

Другие вопросы по теме