为什么UtcDateTime函数没有将偏移量添加到UTC日期?

时间:2018-05-08 06:48:21

标签: c# .net datetime timezone datetimeoffset

对于即时日期时间跟踪,我使用的是DateTimeOffset数据类型。以下函数将用户对应的TimeZone ID偏移量添加到{Date}日期属性DateTimeOffset

根据documentationUtcDateTime将对DateTimeOffset执行时区转换和类型转换。以下代码不是。为什么转换没有发生?

添加TimeSpan偏移的函数,

public static DateTimeOffset GetUtcDateTime (DateTime sourceDateTime, string timeZoneId) {
 TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);
 TimeSpan offset = timeZone.GetUtcOffset (sourceDateTime);
 DateTimeOffset utcTime = new DateTimeOffset (sourceDateTime, offset);
 return utcTime;
 }

在这里我试图转换,

DateTimeOffset utcDate = (DateTime.UtcNow);
DateTime fromUtc = utcDate.DateTime;
DateTimeOffset UtcDate = StaticHandlers.GetUtcDateTime (fromUtc, "America/Los_Angeles");
Console.WriteLine ("UTC now is {0} and UTC Date LA is {1} and UtcDateTime LA is {2}", utcDate, UtcDate, utcDate.UtcDateTime);

输出是,

  

UTC现在是5/8/18 6:43:37 AM +00:00和UTC日期LA是5/8/18   6:43:37 AM -07:00 UtcDateTime LA是5/8/18 6:43:37 AM

更新

我想保留UTC和用户偏移量以便进行跟踪。 DST在这方面很重要。以下示例显示了我在说什么。

DateTime currentDateTime = DateTime.Now;
DateTime beforeDST_LA = new DateTime (2018, 3, 11, 0, 0, 0);
DateTime afterDST_LA = new DateTime (2018, 3, 12, 0, 0, 0);
TimeSpan offsetCurrent = tzi.GetUtcOffset (currentDateTime);
TimeSpan offsetBeforeDST = tzi.GetUtcOffset (beforeDST_LA);
TimeSpan offsetAfterDST = tzi.GetUtcOffset (afterDST_LA);
Console.WriteLine ("Current offset is {0} before DST is {1} and After DST is {2}", offsetCurrent, offsetBeforeDST, offsetAfterDST);
  

在DST为-08:00:00之前和DST之后,当前偏移为-07:00:00   -07:00:00

1 个答案:

答案 0 :(得分:1)

首先,我不会调用您的函数GetUtcDateTime,因为它不是它的功能。它试图在特定时间内为特定时区获取DateTimeOffset,因此请将其称为GetDateTimeOffset

您的代码中缺少的主要概念是DateTime具有.Kind属性,该属性设置DateTimeKind值。您的代码中的几个地方会考虑这种情况:

    在确定偏移量之前,
  • GetUtcOffset会将UtcLocal种转换为所提供的区域。

  • new DateTimeOffset(构造函数)如果类型和偏移量发生冲突,则会出错。

  • 当您将DateTime分配给DateTimeOffset时,隐式转化正在评估该种类。

  • 当您从.DateTime致电DateTimeOffset时,无论偏移如何,总是 <{1}}的种类。

    < / LI>

如果您考虑到所有这些因素,您将意识到在致电Unspecified之前需要亲自检查一下。如果它 GetUtcOffset,则您需要在获取偏移量之前将其转换为指定的时区。

Unspecified

现在处理完毕,请转到下一组问题,这就是你调用它的地方。

public static DateTimeOffset GetDateTimeOffset(DateTime sourceDateTime, string timeZoneId)
{
    TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);

    // here, is where you need to convert
    if (sourceDateTime.Kind != DateTimeKind.Unspecified)
        sourceDateTime = TimeZoneInfo.ConvertTime(sourceDateTime, timeZone);

    TimeSpan offset = timeZone.GetUtcOffset(sourceDateTime);
    return new DateTimeOffset(sourceDateTime, offset);
}

在第1行中,从DateTimeOffset utcDate = (DateTime.UtcNow); DateTime fromUtc = utcDate.DateTime; DateTime的隐式广告设置将偏移设置为DateTimeOffset - 因为00:00DateTime.UtcNow

在第2行中,对.Kind == DateTimeKind.Utc属性的调用设置了.DateTime。从本质上讲,你已经剥离了那种。

所以不要这样,只需将fromUtc.Kind == DateTimeKind.Unspecified直接传递给函数即可。这种情况会持续存在,并且一切都会有效 - 现在DateTime.UtcNow被识别,并且转换正在函数内部发生。

所有这一切,如果您的原始值都是Kind(例如,DateTimeOffset),那么您根本不需要该功能。只需直接使用DateTimeOffset.UtcNow致电TimeZoneInfo.ConvertTime