[英]Why UtcDateTime function is not adding the offset to the UTC date?
For instantaneous DateTime tracking, I am using a DateTimeOffset
datatype. 对于瞬时DateTime跟踪,我使用的是
DateTimeOffset
数据类型。 The following function adds the user corresponding TimeZone ID offset to the UTC DateTime property of DateTimeOffset
下面的函数将用户对应的时区ID偏移到的日期时间UTC属性
DateTimeOffset
According to the documentation , UtcDateTime
will perform both a time zone conversion and a type conversion on a DateTimeOffset
. 根据文档 ,
UtcDateTime
将在DateTimeOffset
上执行时区转换和类型转换。 The following code does not though. 以下代码没有。 Why is the conversion not taking place?
为什么没有进行转换?
Function to add TimeSpan offset, 用于添加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;
}
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
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上午
I want to preserve both UTC and the user offset for tracking purposes. 我想同时保留UTC和用户偏移量以进行跟踪。 DST matters in this context.
在这种情况下,DST很重要。 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 ("Current offset is {0} before DST is {1} and After DST is {2}", offsetCurrent, offsetBeforeDST, offsetAfterDST);
Current offset is -07:00:00 before DST is -08:00:00 and After DST is -07:00:00
当前偏移是DST -08:00:00之前和DST之后-07:00:00 -07:00:00
First, I would not call your function GetUtcDateTime
, because that's not what it does. 首先,我不会调用您的函数
GetUtcDateTime
,因为那不是它的功能。 It is trying to get a DateTimeOffset
for a specific time zone for a specific time, so call it something like GetDateTimeOffset
. 它正在尝试获取特定时区特定时间的
DateTimeOffset
,因此将其命名为GetDateTimeOffset
。
The main concept you're missing in your code is that DateTime
has .Kind
property, which sets a DateTimeKind
value. 您的代码中缺少的主要概念是
DateTime
具有.Kind
属性,该属性设置了DateTimeKind
值。 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. 在确定偏移量之前,
GetUtcOffset
会将Utc
或Local
种类转换为提供的区域。
new DateTimeOffset
(the constructor) will error if the kind and the offset conflict, if you provide an offset. 如果提供偏移量,则种类和偏移量冲突时,
new DateTimeOffset
(构造函数)将出错。
When you assign a DateTime
to a DateTimeOffset
, the implicit conversion is evaluating the kind. 当您将
DateTime
分配给DateTimeOffset
,隐式转换将评估类型。
When you call .DateTime
from the DateTimeOffset
, the kind will always be Unspecified
- regardless of the offset. 当您从
DateTimeOffset
调用.DateTime
,该类型将始终是Unspecified
-与偏移量无关。
If you take all of this into account, you'll realize you need to check the kind yourself before calling GetUtcOffset
. 如果考虑到所有这些,您将意识到需要在调用
GetUtcOffset
之前先检查类型。 If it's not Unspecified
then you'll need to convert it to the specified time zone before getting the offset. 如果未
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);
}
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
. 在第1行中,从
DateTime
到DateTimeOffset
的隐式.Kind == DateTimeKind.Utc
将偏移量设置为00:00
: .Kind == DateTimeKind.Utc
因为DateTime.UtcNow
具有.Kind == DateTimeKind.Utc
。
In line 2, the call to the .DateTime
property sets fromUtc.Kind == DateTimeKind.Unspecified
. 在第2行中,对
.DateTime
属性的调用设置为fromUtc.Kind == DateTimeKind.Unspecified
。 Essentially, you've stripped away the kind. 本质上,您已经剥离了那种。
So instead of this, just pass DateTime.UtcNow
directly into the function. 因此,
DateTime.UtcNow
替代,只需将DateTime.UtcNow
直接传递给该函数。 The kind will persist, and it will all work - now that the Kind
is recognized and the conversion is happening inside the function. 种类将持续存在,并且将全部正常工作-现在可以识别
Kind
,并且函数内将发生转换。
All that said, if your original values are all DateTimeOffset
(example, DateTimeOffset.UtcNow
) then you don't need that function at all. 话虽如此,如果您的原始值全部是
DateTimeOffset
(例如DateTimeOffset.UtcNow
),那么您根本不需要该函数。 Just call TimeZoneInfo.ConvertTime
with the DateTimeOffset
directly. 只需直接使用
DateTimeOffset
调用TimeZoneInfo.ConvertTime
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.