C # Вручную указать часовой пояс в DateTime.ParseExact - PullRequest
3 голосов
/ 03 октября 2019

У меня есть файл журнала, который содержит строки даты / времени, отформатированные так:

2019/10/01 15:30

Как видите, строки не содержат никакой информации о часовом поясе. Тем не менее, я знаю часовой пояс, в котором представлено время.

Если я использую этот код C # на моем собственном ПК, для которого правильно задан местный часовой пояс, время анализируется, как и ожидалось. Я ожидаю преобразовать местное время в UTC для вставки в базу данных.

Time.ParseExact("2019/10/01 15:30", "yyyy/MM/dd HH:mm", provider, DateTimeStyles.AdjustToUniversal & DateTimeStyles.AssumeLocal);

Однако, если я запускаю этот код на одном из хостов Docker, для которого часовой пояс установлен в UTC, времяанализируются как UTCЭто имеет смысл, поскольку на хосте Docker использование UTC AssumeLocal будет таким же, как и UTC.

Простого применения ручного смещения недостаточно из-за перехода на летнее время. Кроме того, некоторые из этих журналов являются историческими и возвращаются до изменения летнего времени, поэтому даже использование алгоритма было бы сложным, и кажется, что это что-то, что уже должно быть решено (то есть, учитывая дату и часовой пояс, определите, находится ли он в летнем времениили нет, а затем настройте на UTC соответственно)

Я хочу иметь возможность явно указать часовой пояс для метки времени, и чтобы структура использовала как данный часовой пояс, так и фактическийдата, чтобы правильно преобразовать время в UTC. Я посмотрел на этот вопрос и на этот вопрос , но все они, похоже, зависят от того, установлена ​​ли сама система в часовом поясе, в котором вы хотите предположить, что дата находится в.

Второй вопрос, кажется, начинает касаться вопроса о предположении известного часового пояса, но затем в ответах просто используется GetUtcOffset в проанализированном времени, чтобы определить количество времени для смещения времени. Это предполагает, что время уже проанализировано в желаемом часовом поясе.

1 Ответ

1 голос
/ 03 октября 2019

Я считаю, что вы ищете TimeZoneInfo .

Используя TimeZoneInfo, вы можете получить необходимую информацию из TimeZoneInfo.FindSystemTimeZoneById .

Эти идентификаторы основаны на операционной системе, но до тех пор, пока все ваши контейнеры находятся в Linux (в качестве примера), вы сможете использовать это для получения времени UTC для хранения. Вы упоминаете, что знаете, в каком часовом поясе находится ваша строка, поэтому вам, вероятно, понадобится что-то, чтобы преобразовать это в идентификаторы, читаемые TimeZoneInfo.

Пример кода взят из TimeZoneInfo.FindSystemTimeZoneById

using System;

public class Example
{
   public static void Main()
   {
      // Get time in local time zone 
      DateTime thisTime = DateTime.Now;
      Console.WriteLine("Time in {0} zone: {1}", TimeZoneInfo.Local.IsDaylightSavingTime(thisTime) ?
                        TimeZoneInfo.Local.DaylightName : TimeZoneInfo.Local.StandardName, thisTime);
      Console.WriteLine("   UTC Time: {0}", TimeZoneInfo.ConvertTimeToUtc(thisTime, TimeZoneInfo.Local));
      // Get Tokyo Standard Time zone
      TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
      DateTime tstTime = TimeZoneInfo.ConvertTime(thisTime, TimeZoneInfo.Local, tst);      
      Console.WriteLine("Time in {0} zone: {1}", tst.IsDaylightSavingTime(tstTime) ?
                        tst.DaylightName : tst.StandardName, tstTime);
      Console.WriteLine("   UTC Time: {0}", TimeZoneInfo.ConvertTimeToUtc(tstTime, tst));
   }
}

// The example displays output like the following when run on a system in the
// U.S. Pacific Standard Time zone:
//       Time in Pacific Standard Time zone: 12/6/2013 10:57:51 AM
//          UTC Time: 12/6/2013 6:57:51 PM
//       Time in Tokyo Standard Time zone: 12/7/2013 3:57:51 AM
//          UTC Time: 12/6/2013 6:57:51 PM
...