下面是我使用的方法,它接受三个输入:
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()
是我的第二个“时钟”
给定这些时间列表和 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/