Как конвертировать Unix timestamp в DateTime и обратно в C#?
Правильная конвертация Unix timestamp в DateTime и обратно в C#
Ваша интуиция верна: Unix timestamp — это количество секунд, прошедших с полуночи 1 января 1970 года по UTC. Проблема в вашем коде в том, что конструктор DateTime(long ticks) интерпретирует переданное число как количество 100-наносекундных интервалов (тиков) с 1 января 0001 года, а не как Unix timestamp. Поэтому вы получаете некорректные даты.
Для решения задачи используйте статические методы класса DateTimeOffset или DateTime, начиная с .NET Framework 4.6 и .NET Core. Вот правильные подходы:
1. Конвертация Unix timestamp в DateTime (секунды)
long unixTimestamp = 1678901234; // 15 марта 2023 года, 10:47:14 UTC
// Способ 1: через DateTimeOffset (рекомендуется)
DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(unixTimestamp);
DateTime dateTime = dateTimeOffset.DateTime; // UTC время
Console.WriteLine(dateTime); // 15.03.2023 10:47:14
// Способ 2: через DateTime вручную (для старых версий .NET)
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime dateTimeManual = epoch.AddSeconds(unixTimestamp);
Console.WriteLine(dateTimeManual); // 15.03.2023 10:47:14
2. Конвертация DateTime в Unix timestamp
DateTime now = DateTime.UtcNow; // Всегда используйте UTC!
// Способ 1: через DateTimeOffset (рекомендуется)
long unixTimestampFromNow = new DateTimeOffset(now).ToUnixTimeSeconds();
Console.WriteLine(unixTimestampFromNow); // текущий timestamp
// Способ 2: вручную (для старых версий .NET)
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long manualTimestamp = (long)(now - epoch).TotalSeconds;
Console.WriteLine(manualTimestamp);
3. Работа с миллисекундами
Если ваш timestamp содержит миллисекунды (например, 1678901234567), используйте методы с суффиксом Milliseconds:
long unixTimestampMs = 1678901234567;
// Из timestamp в DateTime
DateTimeOffset dto = DateTimeOffset.FromUnixTimeMilliseconds(unixTimestampMs);
DateTime dt = dto.DateTime;
// Из DateTime в timestamp с миллисекундами
long msTimestamp = new DateTimeOffset(dt).ToUnixTimeMilliseconds();
4. Важные рекомендации
- Всегда работайте с UTC — Unix timestamp по определению не зависит от часового пояса. Используйте
DateTime.UtcNowвместоDateTime.Now. - Учитывайте Kind — у
DateTimeесть свойствоKind(Utc, Local, Unspecified). При конвертации из timestamp результат всегда имеетDateTimeKind.Utc. - Для локального отображения конвертируйте UTC в локальное время только на этапе вывода:
dateTime.ToLocalTime(). - Проверяйте версию .NET — методы
FromUnixTimeSecondsиToUnixTimeSecondsдоступны с .NET Framework 4.6 и .NET Core 1.0.
Полный пример для вашего случая
public static class UnixConverter
{
private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static DateTime FromUnixTime(long unixTimestamp)
{
return Epoch.AddSeconds(unixTimestamp);
}
public static long ToUnixTime(DateTime dateTime)
{
// Приводим к UTC, если не указано
if (dateTime.Kind == DateTimeKind.Local)
dateTime = dateTime.ToUniversalTime();
else if (dateTime.Kind == DateTimeKind.Unspecified)
dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
return (long)(dateTime - Epoch).TotalSeconds;
}
}
// Использование:
long input = 1678901234;
DateTime result = UnixConverter.FromUnixTime(input);
Console.WriteLine(result); // 15.03.2023 10:47:14
long back = UnixConverter.ToUnixTime(result);
Console.WriteLine(back); // 1678901234
Теперь ваш код будет работать корректно. Главное — помнить про UTC и использовать правильные методы конвертации.
<<Альтернативный подход: использование NodaTime
Если вы работаете с большим количеством операций с датами и временем, рекомендую обратить внимание на библиотеку NodaTime от создателя Joda Time (для Java). Она предоставляет более чистый API и решает многие проблемы, связанные с часовыми поясами.
Установка через NuGet:
Install-Package NodaTime
Пример конвертации:
using NodaTime;
// Unix timestamp в Instant (момент времени)
long unixTimestamp = 1678901234;
Instant instant = Instant.FromUnixTimeSeconds(unixTimestamp);
// Instant в DateTime (локальное время)
DateTimeZone zone = DateTimeZoneProviders.Tzdb["Europe/Moscow"];
ZonedDateTime zoned = instant.InZone(zone);
DateTime localDateTime = zoned.ToDateTimeUnspecified();
// Обратно в Unix timestamp
long back = instant.ToUnixTimeSeconds();
Преимущества NodaTime:
- Чёткое разделение между "моментом времени" (Instant) и "календарным временем" (LocalDateTime, ZonedDateTime).
- Встроенная поддержка всех часовых поясов (IANA tzdata).
- Отсутствие проблем с
DateTimeKind.
Это особенно полезно, если ваше приложение работает с пользователями из разных часовых поясов или требует сложных манипуляций с датами.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги
Локальные и глобальные переменные в Python: как их использовать правильно