问题描述
对于瞬时DateTime跟踪,我使用的是 DateTimeOffset
数据类型。以下函数根据, 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);
输出为
更新,
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);
首先,我不会调用您的函数 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,
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 ("Current offset is {0} before DST is {1} and After DST is {2}", offsetCurrent, offsetBeforeDST, offsetAfterDST);
解决方案 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日期?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!