Работа с датами и временем в netcore

  • Михаил
  • 8 мин. на прочтение
  • 9
  • 01 Sep 2025
  • 01 Sep 2025

Когда вы преобразуете DateTimeOffset в Unix-время (timestamp) в .NET Core, вы всегда получаете значение в UTC. Это связано с тем, что Unix-время — это количество секунд (или миллисекунд), прошедших с 1 января 1970 года 00:00:00 UTC.


Пример на C#

using System;
class Program
{
   static void Main()
   {
       // Создаём DateTimeOffset с локальным временем (например, Москва, UTC+3)
       DateTimeOffset localTime = new DateTimeOffset(
           new DateTime(2025, 9, 1, 12, 0, 0), // 1 сентября 2025, 12:00
           TimeSpan.FromHours(3) // UTC+3
       );
       // Преобразуем в Unix-время (секунды с 1970-01-01 UTC)
       long unixTime = localTime.ToUnixTimeSeconds();
       // Выводим результат
       Console.WriteLine($"Локальное время: {localTime}");
       Console.WriteLine($"Unix-время (UTC): {unixTime}");
       // Для проверки: преобразуем обратно
       DateTimeOffset fromUnix = DateTimeOffset.FromUnixTimeSeconds(unixTime);
       Console.WriteLine($"Обратно в DateTimeOffset: {fromUnix}");
   }
}

Объяснение

  1. DateTimeOffset хранит дату, время и смещение от UTC (например, +03:00 для Москвы).
  2. Метод ToUnixTimeSeconds() автоматически преобразует локальное время в UTC, используя смещение, и только затем считает количество секунд с 1970 года.
  3. Если вы снова преобразуете Unix-время в DateTimeOffset (методом FromUnixTimeSeconds), вы получите время в UTC.

Важно

  • Если вам нужно работать с локальным временем, используйте DateTimeOffset и учитывайте смещение.
  • Unix-время всегда не зависит от часового пояса и основано на UTC.

 

Когда вы работаете с DateTime (не DateTimeOffset) в .NET, у вас есть два ключевых момента, которые определяют, как преобразовать его в Unix-время (UTC):


1. DateTime.Kind — тип времени

У DateTime есть свойство Kind, которое может принимать три значения:

  • DateTimeKind.Unspecified — не указано, UTC это или локальное время (по умолчанию).
  • DateTimeKind.Utc — время в UTC.
  • DateTimeKind.Local — локальное время (с учётом часового пояса).

2. Как преобразовать в Unix-время (UTC)

a) Если DateTime уже в UTC (Kind == Utc):

DateTime utcTime = DateTime.UtcNow; // или любое другое UTC-время
long unixTime = new DateTimeOffset(utcTime).ToUnixTimeSeconds();

Здесь смещение не нужно — время уже в UTC.


b) Если DateTime — локальное время (Kind == Local):

DateTime localTime = DateTime.Now; // локальное время
DateTimeOffset localTimeOffset = new DateTimeOffset(localTime);
long unixTime = localTimeOffset.ToUnixTimeSeconds();

Метод ToUnixTimeSeconds() автоматически учтёт смещение локального времени относительно UTC.


c) Если DateTime — неопределённого типа (Kind == Unspecified):

В этом случае вы должны явно указать, считать ли это время UTC или локальным. Например:

DateTime unspecifiedTime = new DateTime(2025, 9, 1, 12, 0, 0); // Kind = Unspecified
// Вариант 1: считаем, что это UTC
DateTimeOffset utcTimeOffset = new DateTimeOffset(unspecifiedTime, TimeSpan.Zero);
long unixTime = utcTimeOffset.ToUnixTimeSeconds();
// Вариант 2: считаем, что это локальное время (например, UTC+3)
DateTimeOffset localTimeOffset = new DateTimeOffset(unspecifiedTime, TimeSpan.FromHours(3));
long unixTimeLocal = localTimeOffset.ToUnixTimeSeconds();

Пример с объяснением

using System;
class Program
{
   static void Main()
   {
       // Локальное время (например, Москва, UTC+3)
       DateTime localTime = DateTime.Now;
       Console.WriteLine($"Локальное время: {localTime}, Kind: {localTime.Kind}");
       // Преобразуем в Unix-время (автоматически учтёт смещение)
       DateTimeOffset localTimeOffset = new DateTimeOffset(localTime);
       long unixTime = localTimeOffset.ToUnixTimeSeconds();
       Console.WriteLine($"Unix-время (UTC): {unixTime}");
       // Обратно в DateTimeOffset (будет в UTC)
       DateTimeOffset fromUnix = DateTimeOffset.FromUnixTimeSeconds(unixTime);
       Console.WriteLine($"Обратно в DateTimeOffset (UTC): {fromUnix}");
   }
}

Выводы

  • DateTime без Kind или с Kind = Unspecified требует явного указания смещения.
  • DateTime.Kind = Utc или DateTime.Kind = Local позволяют автоматически корректно преобразовать в Unix-время.
  • Unix-время всегда основано на UTC.

Если нужно работать с конкретным часовым поясом (например, не локальным, а другим), используйте TimeZoneInfo для преобразования.

Вот пример, как работать с конкретным часовым поясом (например, не локальным, а, скажем, Нью-Йорком или Токио) при преобразовании DateTime в Unix-время (UTC).


Пример: Преобразование DateTime в Unix-время с учётом произвольного часового пояса

using System;
class Program
{
   static void Main()
   {
       // 1. Создаём DateTime (без указания Kind)
       DateTime unspecifiedTime = new DateTime(2025, 9, 1, 12, 0, 0);
       Console.WriteLine($"Исходное время: {unspecifiedTime}, Kind: {unspecifiedTime.Kind}");
       // 2. Указываем часовой пояс (например, Нью-Йорк, UTC-4)
       TimeZoneInfo nyTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
       DateTime nyTime = TimeZoneInfo.ConvertTimeFromUtc(unspecifiedTime, nyTimeZone);
       Console.WriteLine($"Время в Нью-Йорке: {nyTime}, Kind: {nyTime.Kind}");
       // 3. Преобразуем в DateTimeOffset с правильным смещением
       DateTimeOffset nyTimeOffset = new DateTimeOffset(nyTime, nyTimeZone.GetUtcOffset(nyTime));
       Console.WriteLine($"DateTimeOffset для Нью-Йорка: {nyTimeOffset}");
       // 4. Получаем Unix-время (UTC)
       long unixTime = nyTimeOffset.ToUnixTimeSeconds();
       Console.WriteLine($"Unix-время (UTC): {unixTime}");
       // 5. Проверяем: преобразуем обратно
       DateTimeOffset fromUnix = DateTimeOffset.FromUnixTimeSeconds(unixTime);
       Console.WriteLine($"Обратно в DateTimeOffset (UTC): {fromUnix}");
   }
}

Объяснение шагов:

DateTime без Kind Создаём DateTime с неопределённым типом (Unspecified). Это может быть любое время, но без привязки к часовому поясу.

Преобразование в нужный часовой пояс Используем TimeZoneInfo.FindSystemTimeZoneById для получения информации о часовом поясе (например, Нью-Йорк — "Eastern Standard Time"). Метод TimeZoneInfo.ConvertTimeFromUtc преобразует время из UTC в указанный часовой пояс.

Создание DateTimeOffset Преобразуем DateTime в DateTimeOffset, явно указывая смещение для данного времени в выбранном часовом поясе.

Получение Unix-времени Метод ToUnixTimeSeconds() автоматически преобразует время в UTC и возвращает количество секунд с 1970 года.

Обратная проверка Преобразуем Unix-время обратно в DateTimeOffset, чтобы убедиться, что всё корректно.


Важные моменты:

  • Идентификаторы часовых поясов зависят от ОС. Для Windows используйте имена из реестра Windows, для Linux — из базы данных IANA.
  • Если вы работаете с локальным временем, используйте TimeZoneInfo.Local вместо конкретного пояса.
  • Если DateTime уже в UTC, просто создайте DateTimeOffset с нулевым смещением.

Пример для Токио (UTC+9)

TimeZoneInfo tokyoTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
DateTime tokyoTime = TimeZoneInfo.ConvertTimeFromUtc(unspecifiedTime, tokyoTimeZone);
DateTimeOffset tokyoTimeOffset = new DateTimeOffset(tokyoTime, tokyoTimeZone.GetUtcOffset(tokyoTime));
long unixTimeTokyo = tokyoTimeOffset.ToUnixTimeSeconds();