c# - 使用 TimeZoneInfo 调整时区的夏令时偏移

标签 c# datetime timezone offset dst

下面是我使用的方法,它接受三个输入:

dateTimeInput 这是表示日期的字符串。

inputFormat 是我的 format 字符串,如下格式:yyyy-MM-dd'T'HH:mm:sszzz

timeZoneStandardName 是从 var TimeZoneList = TimeZoneInfo.GetSystemTimeZones(); 检索的唯一时区标识符,其中 ID 是通过 timeZoneList.Id 检索的。

我主要使用 TimeZoneInfo 来获取小时和分钟偏移量,因为它非常明确地表明它是什么城市/时区,例如UTC 是输入字符串。

public int dateTimeToUnixTime(string dateTimeInput, string inputFormat, string timeZoneStandardName)
{
    DateTime result;
    CultureInfo provider = CultureInfo.InvariantCulture;
    TimeZoneInfo objTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneStandardName);
    int timeZoneHours = objTimeZoneInfo.BaseUtcOffset.Hours;
    int timeZoneMinutes = objTimeZoneInfo.BaseUtcOffset.Minutes;

    // if input format is "yyyy-MM-dd'T'HH:mm:sszzz"
    if (inputFormat == "yyyy-MM-dd'T'HH:mm:sszzz")
    {
        result = DateTime.ParseExact(dateTimeInput, inputFormat, provider, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
        int unixTime = (Int32)(result.Subtract(Epoch)).TotalSeconds;
        return unixTime;
    }
    else
    {
        // if other input formats
        result = DateTime.ParseExact(dateTimeInput, inputFormat, provider, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
        int unixTime = (Int32)(result.AddHours(-timeZoneHours).AddMinutes(-timeZoneMinutes).Subtract(Epoch)).TotalSeconds;
        return unixTime;
    }
}

我的第二种方法接受 Unix 时间戳和时区说明符,并输出为位置相关的时间:

public string unixTimeToDateTime(int unixInput, string outputFormat, string timeZoneStandardName)
{
    // output format is "yyyy-MM-dd'T'HH:mm:sszzz"
    TimeZoneInfo objTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneStandardName);
    int timeZoneHours = objTimeZoneInfo.BaseUtcOffset.Hours;
    int timeZoneMinutes = objTimeZoneInfo.BaseUtcOffset.Minutes;
    if (outputFormat == "yyyy-MM-dd'T'HH:mm:sszzz")
    {
        System.DateTime dateTime = Epoch.AddSeconds(unixInput);
        return dateTime.AddHours(timeZoneHours).AddMinutes(timeZoneMinutes).ToString("yyyy-MM-dd'T'HH:mm:ss") + toTimeSpan(timeZoneHours, timeZoneMinutes);
    }
    // output format is not
    else
    {
        System.DateTime dateTime = Epoch.AddSeconds(unixInput).AddHours(timeZoneHours).AddMinutes(timeZoneMinutes);
        return dateTime.ToString(outputFormat);
    }
}

例如,这是 Grasshopper 组件中的这个方法,我可以向您展示我的意思。 dateTimeToUnixTime() 是我的第一个“时钟”,而 unixTimeToDateTime() 是我的第二个“时钟”

enter image description here

给定这些时间列表和 EST 时区标记的输入,并给定这些日期(请注意,2014 年 11 月 2 日凌晨 1-2 点是我们再次进行 DST 调整的时间),理论上,此方法应该将其时区调整为抵消一小时。

我知道 TimeZoneInfo 支持 DST,因为我可以使用下面的方法来显示相应时区的 DST 状态的 bool

    var TimeZoneList = TimeZoneInfo.GetSystemTimeZones();

    for (int i = 0; i < TimeZoneList.Count; i++)
    {
        Console.WriteLine(TimeZoneList[i].Id + ": " + TimeZoneList[i].SupportsDaylightSavingTime);
    }

我的问题是,我的 dateTimeToUnixTime() 方法中缺少什么,该方法允许根据 DST 条件进行自动调整和偏移?

最佳答案

假设您的纪元从 1970 年 1 月 1 日开始,那么我们可以使用 DateTimeOffset _1970 作为您的纪元,将所需的秒数添加到 _1970 然后使用 TimeZoneInfo.ConvertTime获取指定时区的日期时间并进行夏令时调整(如果适用)。请务必使用 DateTimeOffset 而不是 DateTime,以便在获取字符串时保留正确的偏移量。

private static readonly DateTimeOffset _1970 = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
public string UnixTimeToDateTime(int unixInput, string outputFormat, string timeZoneStandardName)
{
    var objTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneStandardName);
    var utcDate = _1970.AddSeconds(unixInput);
    DateTimeOffset localDate = TimeZoneInfo.ConvertTime(utcDate, objTimeZoneInfo);
    return localDate.ToString(outputFormat);
}

//1970-01-01T13:00:00+13:00
Console.WriteLine( UnixTimeToDateTime(0, "yyyy-MM-dd'T'HH:mm:sszzz", "New Zealand Standard Time"));

//1970-01-01T08:00:00+08:00
Console.WriteLine(UnixTimeToDateTime(0, "yyyy-MM-dd'T'HH:mm:sszzz", "Singapore Standard Time"));

//1969-12-31T19:00:00-05:00
Console.WriteLine(UnixTimeToDateTime(0, "yyyy-MM-dd'T'HH:mm:sszzz", "Eastern Standard Time"));

需要注意的是,使用TimeZoneInfo可能没有accurate information关于历史日期调整,所以如果这对您很重要,那么您最好使用诸如 Node Time 之类的库。 .

关于c# - 使用 TimeZoneInfo 调整时区的夏令时偏移,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22690533/

相关文章:

c# - date.IsWithIn(x months).Of(Comparison Date) 之类的 C# 语法是什么?

Java 毫秒时间,每小时分辨率

timezone - Plone MailHost 发送带有澳大利亚时区的错误日期 header

python - 为什么 pytz localize() 不生成一个 datetime 对象,其 tzinfo 与本地化它的 tz 对象相匹配?

c# - 在没有 ICommand 的情况下将事件绑定(bind)到 ViewModel 的方法

c# - YouTube Feed解析XML C# Razor

python pandas日期时间转换为日期

java - Joda - 如何在不忽略时区的情况下比较两个 DateTime 对象

c# - MS Graph - 401 未经授权,看似具有适当的 token 和访问权限

C# Process Start 需要带双引号的参数 - 它们消失了