TimeZoneInfo.ConvertTimeToUtc问题

时间:2013-05-01 17:09:57

标签: c# .net datetime

我们遇到了一个问题,一个开发人员创建了以下代码,并且它可以在他的DEV环境中运行。但是当它被检入QA时,代码会出现以下错误消息:

myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone);
  

由于提供的DateTime无法完成转换   没有正确设置Kind属性。例如,当   Kind属性是DateTimeKind.Local,源时区必须是   TimeZoneInfo.Local。

在我的DEV环境中,上面的代码生成与QA服务器相同的错误。我应用以下更改来解决问题:

DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified);
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone);

为什么第一个代码示例适用于DEV1的环境但在我的DEV环境和QA服务器上中断?

4 个答案:

答案 0 :(得分:46)

这取决于myRecord.StartTime的起源方式。

  • 如果您是从DateTime.Now获得的,那么它会有Local种。
  • 如果您是从DateTime.UtcNow获得的,则会有Utc种类。
  • 如果您是从new DateTime(2013,5,1)获得的,则会有Unspecified种类。

这还取决于您从哪里获得myTimeZone。例如:

  • TimeZoneInfo.Local
  • TimeZoneInfo.Utc
  • TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

TimeZoneInfo.ConvertTimeToUtc功能只有在区域与您提供的区域匹配时才会运行。如果两者都是本地的,或者两者都是UTC,那么它将起作用。如果您给它一个特定的区域,那么该类型应该是未指定的。此行为是documented on MSDN

您可以轻松地一致地重现异常:

var tz = TimeZoneInfo.FindSystemTimeZoneById("Fiji Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, tz);

假设你不住在斐济,每次都会出错。你基本上说,“把我当地的时间转换成其他区域的utc” - 这没有用。

它可能适用于您的开发环境,因为您为myTimeZone测试的值恰好是开发人员的本地区域。

关于你的改变 - 确保你可以强制指明这种类型,并改变你正在做的事情的意义,这样才有意义。但你确定这是你想要的吗?事前约会的.Kind是多少?如果它还不是Unspecified,那么它带有一些意图。您应该回到这些数据的来源,并确保它符合您的期望。

如果所有这些听起来都疯狂,疯狂,令人沮丧和奇怪,那是因为DateTime对象很臭。这是一些额外的阅读:

您可以考虑使用NodaTime代替。它的API将阻止您犯这些类型的常见错误。

答案 1 :(得分:1)

我在这里找到了一个非常简单的解决方案 https://kiranpatils.wordpress.com/2011/01/09/the-conversion-could-not-be-completed-because-the-supplied-datetime-did-not-have-the-kind-property-set-correctly-for-example-when-the-kind-property-is-datetimekind-local-the-source-time-zone-must/

只有在使用DateTime.Now时才会出现这种情况。我更新了我的代码,如下所示,它再次运行:)

DateTime currentTime = new DateTime(DateTime.Now.Ticks,DateTimeKind.Unspecified);

答案 2 :(得分:0)

基本上是以前的答案中所说的,但要精简:

DateTime.NowDateTime.Today 将 Kind 设置为 Local,因此将其更改为 Unspecified

在处理日期的方法中:

// Incoming date has DateTimeKind.Local 
 var localDateTime = DateTime.Now;

// Set to unspecified
 var unspecifiedDateTime = DateTime.SpecifyKind(localDateTime, DateTimeKind.Unspecified); 

我只是在部署时收到这个,然后意识到一个库正在将 DateTime.Now 而不是 new DateTime(...) 传递给一个方法。

答案 3 :(得分:-2)

在C#中


public static DateTime IndianDateTime(DateTime currentTime)
{
    DateTime cstTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, "India Standard Time");
    return cstTime;
}

在VB中


Public Shared Function IndianDateTime(ByVal currentTime As DateTime) As DateTime
        Dim cstTime As DateTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, "India Standard Time")
        Return cstTime
    End Function