当 kind 为 Utc 时从日期时间 UTC 转换为 datetimeoffset 时出错
Error converting from datetime UTC to datetimeoffset when kind is Utc
将 UTC 格式的 DateTime 转换为 DateTimeOffset 时出错
当种类是 Utc 时。
origDateTime 来自网络服务,所以我无法控制内容或格式。
在大多数情况下,它带有 Kind=Unspecified (即使时间在 Utc 中也很艰难)然后它就可以工作,但在极少数情况下 Kind=Utc 然后转换为 DateTimeOffset 抛出异常:
"The UTC Offset for Utc DateTime instances must be 0.\r\nParameter name: offset"
我该如何解决?
try {
//cause error !!!!
DateTime databaseUtcTime = DateTime.Parse("4/2/2016 6:25:20 PM");
var localTimeTemp = databaseUtcTime.ToLocalTime();
DateTime origDateTime = localTimeTemp.ToUniversalTime();
//this is working
//DateTime origDateTime = DateTime.Parse("4/2/2016 6:25:20 PM");
string timeZoneName = "Pacific Standard Time";
TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
DateTimeOffset localTime = new DateTimeOffset(origDateTime, localTimeZone.GetUtcOffset(origDateTime));
return localTime;
}
catch (Exception ex) {
string msg = ex.Message;
return null;
}
因此,如果您始终将 DateTimeKind
设置为 Unspecified
,您的问题就会得到解决,不是吗?
试试这个:
DateTime origDateTime = new DateTime(origDateTimeUnspecifiedKind.Ticks, DateTimeKind.Unspecified);
与您的示例集成:
try
{
//cause error !!!!
DateTime databaseUtcTime = DateTime.Parse("4/2/2016 6:25:20 PM");
var localTimeTemp = databaseUtcTime.ToLocalTime();
DateTime origDateTimeUnspecifiedKind = localTimeTemp.ToUniversalTime();
// FIX: specify the kind
DateTime origDateTime = new DateTime(origDateTimeUnspecifiedKind.Ticks, DateTimeKind.Unspecified);
//this is working
//DateTime origDateTime = DateTime.Parse("4/2/2016 6:25:20 PM");
string timeZoneName = "Pacific Standard Time";
TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
DateTimeOffset localTime = new DateTimeOffset(origDateTime, localTimeZone.GetUtcOffset(origDateTime));
return localTime;
}
catch (Exception ex)
{
string msg = ex.Message;
return null;
}
几件事:
如果你真的需要切换DateTime
的Kind
而不调整它的值,使用DateTime.SpecifyKind
。它比处理蜱虫更干净。不过,我认为你真的不需要这样做。
不要使用 ToLocalTime
或 ToUniversalTime
。这两个都会在转换过程中使用服务器的时区设置。
我不确定您的真实代码是否真的在解析字符串,因为您指出它来自数据库。如果它来自数据库,则不应涉及字符串解析。只需执行以下操作:
DateTime databaseUtcTime = (DateTime) yourDataReader["YourDataField"];
输入后,您可以使用 TimeZoneInfo.ConvertTime
函数进行转换。您现有的代码没有正确转换时间,它只是分配了一个偏移量而没有正确调整时间值。
由于您希望输出为 datetimeoffset
,因此最简单的方法是首先将输入 datetime
转换为偏移量为零的 datetimeoffset
(因为它来自来自 UTC)。
DateTimeOffset dtoUtc = new DateTimeOffset(databaseUtcTime, TimeSpan.Zero);
那么转换起来就相当简单了:
string timeZoneName = "Pacific Standard Time";
TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
DateTimeOffset dtoLocal = TimeZoneInfo.ConvertTime(dtoUtc, localTimeZone);
将 UTC 格式的 DateTime 转换为 DateTimeOffset 时出错 当种类是 Utc 时。 origDateTime 来自网络服务,所以我无法控制内容或格式。 在大多数情况下,它带有 Kind=Unspecified (即使时间在 Utc 中也很艰难)然后它就可以工作,但在极少数情况下 Kind=Utc 然后转换为 DateTimeOffset 抛出异常: "The UTC Offset for Utc DateTime instances must be 0.\r\nParameter name: offset" 我该如何解决?
try {
//cause error !!!!
DateTime databaseUtcTime = DateTime.Parse("4/2/2016 6:25:20 PM");
var localTimeTemp = databaseUtcTime.ToLocalTime();
DateTime origDateTime = localTimeTemp.ToUniversalTime();
//this is working
//DateTime origDateTime = DateTime.Parse("4/2/2016 6:25:20 PM");
string timeZoneName = "Pacific Standard Time";
TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
DateTimeOffset localTime = new DateTimeOffset(origDateTime, localTimeZone.GetUtcOffset(origDateTime));
return localTime;
}
catch (Exception ex) {
string msg = ex.Message;
return null;
}
因此,如果您始终将 DateTimeKind
设置为 Unspecified
,您的问题就会得到解决,不是吗?
试试这个:
DateTime origDateTime = new DateTime(origDateTimeUnspecifiedKind.Ticks, DateTimeKind.Unspecified);
与您的示例集成:
try
{
//cause error !!!!
DateTime databaseUtcTime = DateTime.Parse("4/2/2016 6:25:20 PM");
var localTimeTemp = databaseUtcTime.ToLocalTime();
DateTime origDateTimeUnspecifiedKind = localTimeTemp.ToUniversalTime();
// FIX: specify the kind
DateTime origDateTime = new DateTime(origDateTimeUnspecifiedKind.Ticks, DateTimeKind.Unspecified);
//this is working
//DateTime origDateTime = DateTime.Parse("4/2/2016 6:25:20 PM");
string timeZoneName = "Pacific Standard Time";
TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
DateTimeOffset localTime = new DateTimeOffset(origDateTime, localTimeZone.GetUtcOffset(origDateTime));
return localTime;
}
catch (Exception ex)
{
string msg = ex.Message;
return null;
}
几件事:
如果你真的需要切换
DateTime
的Kind
而不调整它的值,使用DateTime.SpecifyKind
。它比处理蜱虫更干净。不过,我认为你真的不需要这样做。不要使用
ToLocalTime
或ToUniversalTime
。这两个都会在转换过程中使用服务器的时区设置。我不确定您的真实代码是否真的在解析字符串,因为您指出它来自数据库。如果它来自数据库,则不应涉及字符串解析。只需执行以下操作:
DateTime databaseUtcTime = (DateTime) yourDataReader["YourDataField"];
输入后,您可以使用
TimeZoneInfo.ConvertTime
函数进行转换。您现有的代码没有正确转换时间,它只是分配了一个偏移量而没有正确调整时间值。由于您希望输出为
datetimeoffset
,因此最简单的方法是首先将输入datetime
转换为偏移量为零的datetimeoffset
(因为它来自来自 UTC)。DateTimeOffset dtoUtc = new DateTimeOffset(databaseUtcTime, TimeSpan.Zero);
那么转换起来就相当简单了:
string timeZoneName = "Pacific Standard Time"; TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName); DateTimeOffset dtoLocal = TimeZoneInfo.ConvertTime(dtoUtc, localTimeZone);