c# 从固定时区转换 DateTime

c# Convert DateTime from fixed timezone

我正在从这样的外部 API 日期读取数据:

2022-05-1307:05:00

2022-05-13 13:00:00 ...

这些日期以 CET 时间固定。我想将它们转换成 UTC 格式,如“yyyy-MM-ddTHH:mm:sszzz”,这样我就可以看到 UTC 偏移量 +02:00。

问题是我没有找到一种方法来指定我的日期是在 CET 时区内。 ConvertTime、ConvertTimeToUtc 等函数不起作用。

我的代码是:

    var time = new DateTime(2022,5,26,8,15,00, DateTimeKind.Unspecified);    // 2022-05-26 8:15:00 CET
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
    DateTime cet = TimeZoneInfo.ConvertTime(time, tz); // non sense, as no timezone info in time...
    var str = cet.ToString("yyyy-MM-ddTHH:mm:sszzz");

如何解决?

您可以使用以下方法手动设置小时数:

// Currently CET is ahead of UTC by 2 hours
time = time.AddHours(-2);

然后您可以格式化日期时间对象而无需担心时区。

编辑:添加夏令时。

首先你要检查你是否处于夏令时生效的时间。

首先获取日期时间,然后检查它是否处于夏令时。 3月最后一个星期日开始实行夏令时,10月最后一个星期日取消

currentTime = DateTime.Now();
string currentMonth = currentTime.ToString("MM");
string currentDay = currentTime.ToString("DD");

// Daylight saving is in effect
if ( currentMonth > '3' && currentMonth < '10' ) {
    time = time.AddHours(-2);
}

// Daylight saving is not in effect
else if ( currentMonth < '3' || currentMonth > '10' ) {
    time = time.AddHours(-1);
}

    // If it is march or october
else if(currentMonth == '3' || currentMonth == '10')
{

    // Find the last sunday
    var lastSunday = new DateTime(currentTime.Year,currentTime.Month,1);
    lastSunday = lastSunday.AddMonths(1).AddDays(-1);
    while (lastSunday.DayOfWeek != DayOfWeek.Sunday)
    {
        lastSunday = lastSunday.AddDays(-1);
    }
    string sunday = lastSunday.ToString("DD");

     // If it is march, check to see if the day is after or before last sunday
     if(currentMonth == '3'){ 
         if( currentDay > sunday )
         {
             // Daylight saving is in effect
             time = time.AddHours(-2);
         }
         else
         {
             // It is not in effect
             time = time.AddHours(-1);
         }
     }
     // If it is october, check to see if the day is after last sunday or not
     else if(currentMonth == '10'){
         if( currentDay > sunday )
         {
             // Daylight saving is not in effect
             time = time.AddHours(-1);
         }
         else
         {
             // It is in effect
             time = time.AddHours(-2);
         }
     }

}

有一种更简洁的方法:

public static DateTime ParseCET(string dt)
{
    var cet = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
    var localTime = DateTime.Parse(dt);
    return TimeZoneInfo.ConvertTimeToUtc(localTime, cet);
}

输出一致且正确,始终遵守夏令时:

// winter time - prints "2/1/2022 11:00:00 AM"
Console.WriteLine(ParseCET("2022-02-01 12:00:00").ToString());

// summer time - prints "8/1/2022 10:00:00 AM"
Console.WriteLine(ParseCET("2022-08-01 12:00:00").ToString());

边缘情况:

  1. 当夏令时从冬令时变为夏令时时,时钟从02:00:00跳到03:00:01,因此没有 2022-03-27 02:30:00 CET.

本例根据documentation抛出异常:

If dateTime corresponds to an invalid time, this method throws an ArgumentException.

  1. 当夏令时改为冬令时时,时钟从03:00:00跳到02:00:01,因此例如 2022-10-30 02:30:00 CET 在逻辑上可以转换为 00:30:00 UTC 或 01:30:00 UTC

在这种情况下,根据 documentation 标准(冬季)时间假设:

If dateTime corresponds to an ambiguous time, this method assumes that it is the standard time of the source time zone.