对于即时日期时间跟踪,我使用的是DateTimeOffset
数据类型。以下函数将用户对应的TimeZone ID偏移量添加到{Date}日期属性DateTimeOffset
根据documentation,UtcDateTime
将对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
答案 0 :(得分:1)
首先,我不会调用您的函数GetUtcDateTime
,因为它不是它的功能。它试图在特定时间内为特定时区获取DateTimeOffset
,因此请将其称为GetDateTimeOffset
。
您的代码中缺少的主要概念是DateTime
具有.Kind
属性,该属性设置DateTimeKind
值。您的代码中的几个地方会考虑这种情况:
GetUtcOffset
会将Utc
或Local
种转换为所提供的区域。
new DateTimeOffset
(构造函数)如果类型和偏移量发生冲突,则会出错。
当您将DateTime
分配给DateTimeOffset
时,隐式转化正在评估该种类。
当您从.DateTime
致电DateTimeOffset
时,无论偏移如何,总是 <{1}}的种类。
如果您考虑到所有这些因素,您将意识到在致电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:00
有DateTime.UtcNow
。
在第2行中,对.Kind == DateTimeKind.Utc
属性的调用设置了.DateTime
。从本质上讲,你已经剥离了那种。
所以不要这样,只需将fromUtc.Kind == DateTimeKind.Unspecified
直接传递给函数即可。这种情况会持续存在,并且一切都会有效 - 现在DateTime.UtcNow
被识别,并且转换正在函数内部发生。
所有这一切,如果您的原始值都是Kind
(例如,DateTimeOffset
),那么您根本不需要该功能。只需直接使用DateTimeOffset.UtcNow
致电TimeZoneInfo.ConvertTime
。