为什么UtcDateTime函数未将偏移量添加到UTC日期? [英] Why UtcDateTime function is not adding the offset to the UTC date?

查看:113
本文介绍了为什么UtcDateTime函数未将偏移量添加到UTC日期?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于瞬时DateTime跟踪,我使用的是 DateTimeOffset 数据类型。以下函数根据将用户对应的TimeZone ID偏移量添加到 DateTimeOffset

的UTC DateTime属性中,根据 href = https://docs.microsoft.com/zh-cn/dotnet/standard/datetime/converting-between-datetime-and-offset rel = nofollow noreferrer>文档 UtcDateTime 将在 DateTimeOffset 上执行时区转换和类型转换。以下代码没有。为什么不进行转换?



用于添加TimeSpan偏移量的函数,

  public static DateTimeOffset GetUtcDateTime(DateTime sourceDateTime,字符串timeZoneId){
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
TimeSpan offset = timeZone.GetUtcOffset(sourceDateTime);
DateTimeOffset utcTime =新的DateTimeOffset(sourceDateTime,偏移量);
返回utcTime;
}

在这里我要转换的地方,

  DateTimeOffset utcDate =(DateTime.UtcNow); 
DateTime fromUtc = utcDate.DateTime;
DateTimeOffset UtcDate = StaticHandlers.GetUtcDateTime(fromUtc, America / Los_Angeles);
Console.WriteLine( UTC现在为{0},UTC日期LA为{1},UtcDateTime LA为{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/5/18 6:43:37 AM




更新,



<我想同时保留UTC和用户偏移量以进行跟踪。在这种情况下,DST很重要。下面的示例显示了我在说什么。

  DateTime currentDateTime = DateTime.Now; 
DST_LA之前的DateTime =新的DateTime(2018、3、11、0、0、0);
DST_LA之后的DateTime =新的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(& DST为{1}之前的当前偏移量为{0},而DST为{2}之后的当前偏移量,offsetCurrent,offsetBeforeDST,offsetAfterDST);




当前偏移量是DST为-08之前的-07:00:00 :00:00和DST之后是
-07:00:00



解决方案

首先,我不会调用您的函数 GetUtcDateTime ,因为这不是它的功能。它正在尝试获取特定时间段中特定时间的 DateTimeOffset ,因此将其称为 GetDateTimeOffset



您的代码中缺少的主要概念是 DateTime 具有属性,用于设置 DateTimeKind 值。在代码中的多个位置都考虑了这种类型:




  • GetUtcOffset 会将 Utc Local 种类转换为确定偏移量之前提供的区域。


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


  • 当您将 DateTime 分配给 DateTimeOffset 时,


  • 当您从 .DateTime 时,将对其进行隐式转换。 > DateTimeOffset ,该类型将始终未指定-而不考虑偏移量。




如果考虑到所有这些,您将意识到需要在调用 GetUtcOffset之前先检查一下种类。。如果不是 未指定,则需要先将其转换为指定的时区,然后再获取偏移。

 公共静态DateTimeOffset GetDateTimeOffset(DateTime sourceDateTime,字符串timeZoneId)
{
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById (timeZoneId);

//在这里,如果(sourceDateTime.Kind!= DateTimeKind.Unspecified)
sourceDateTime = TimeZoneInfo.ConvertTime(sourceDateTime,timeZone);

TimeSpan偏移量= timeZone.GetUtcOffset(sourceDateTime);
返回新的DateTimeOffset(sourceDateTime,offset);
}

现在已经解决了,转到下一组问题,即

  DateTimeOffset utcDate =(DateTime.UtcNow); 
DateTime fromUtc = utcDate.DateTime;

在第1行中,从 DateTime 设置为 DateTimeOffset 将偏移设置为 00:00 -因为 DateTime.UtcNow 具有 .Kind == DateTimeKind.Utc



在第2行中,对 .DateTime 属性设置 fromUtc.Kind == DateTimeKind.Unspecified 。本质上,您已经剥离了这种类型。



因此,与其代替,只需将 DateTime.UtcNow 传递给功能。这种类型将持续存在,并且将全部正常工作-现在,已识别出种类并且转换正在函数内进行。



所有这些,如果您的原始值全部为 DateTimeOffset (例如, DateTimeOffset.UtcNow ),那么您根本不需要那个功能。只需直接使用 DateTimeOffset 调用 TimeZoneInfo.ConvertTime


For instantaneous DateTime tracking, I am using a DateTimeOffset datatype. The following function adds the user corresponding TimeZone ID offset to the UTC DateTime property of DateTimeOffset

According to the documentation, UtcDateTime will perform both a time zone conversion and a type conversion on a DateTimeOffset. The following code does not though. Why is the conversion not taking place?

Function to add TimeSpan offset,

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;
 }

and here where I am trying to convert,

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);

the output is,

UTC now is 5/8/18 6:43:37 AM +00:00 and and UTC Date LA is 5/8/18 6:43:37 AM -07:00 UtcDateTime LA is 5/8/18 6:43:37 AM

update,

I want to preserve both UTC and the user offset for tracking purposes. DST matters in this context. The example below shows what I am talking about.

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 (&quot;Current offset is {0} before DST is {1} and After DST is {2}&quot;, offsetCurrent, offsetBeforeDST, offsetAfterDST);

Current offset is -07:00:00 before DST is -08:00:00 and After DST is -07:00:00

解决方案

First, I would not call your function GetUtcDateTime, because that's not what it does. It is trying to get a DateTimeOffset for a specific time zone for a specific time, so call it something like GetDateTimeOffset.

The main concept you're missing in your code is that DateTime has .Kind property, which sets a DateTimeKind value. The kind is taken into consideration by several places in your code:

  • GetUtcOffset will convert Utc or Local kinds to the zone provided before determining the offset.

  • new DateTimeOffset (the constructor) will error if the kind and the offset conflict, if you provide an offset.

  • When you assign a DateTime to a DateTimeOffset, the implicit conversion is evaluating the kind.

  • When you call .DateTime from the DateTimeOffset, the kind will always be Unspecified - regardless of the offset.

If you take all of this into account, you'll realize you need to check the kind yourself before calling GetUtcOffset. If it's not Unspecified then you'll need to convert it to the specified time zone before getting the offset.

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);
}

Now that this is handled, turn to the next set of problems, which is where you call it.

DateTimeOffset utcDate = (DateTime.UtcNow);
DateTime fromUtc = utcDate.DateTime;

In line 1, the implicit cast from DateTime to DateTimeOffset sets the offset to 00:00 - because DateTime.UtcNow has .Kind == DateTimeKind.Utc.

In line 2, the call to the .DateTime property sets fromUtc.Kind == DateTimeKind.Unspecified. Essentially, you've stripped away the kind.

So instead of this, just pass DateTime.UtcNow directly into the function. The kind will persist, and it will all work - now that the Kind is recognized and the conversion is happening inside the function.

All that said, if your original values are all DateTimeOffset (example, DateTimeOffset.UtcNow) then you don't need that function at all. Just call TimeZoneInfo.ConvertTime with the DateTimeOffset directly.

这篇关于为什么UtcDateTime函数未将偏移量添加到UTC日期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆