TimeZoneInfo.ConvertTimeToUtc问题

Jer*_*rry 30 .net c# datetime

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

myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone);
Run Code Online (Sandbox Code Playgroud)

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

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

DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified);
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone);
Run Code Online (Sandbox Code Playgroud)

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

Mat*_*int 52

这取决于它是如何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,那么它将起作用.如果您给它一个特定的区域,那么该类型应该是未指定的.MSDN记录了此行为.

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

var tz = TimeZoneInfo.FindSystemTimeZoneById("Fiji Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, tz);
Run Code Online (Sandbox Code Playgroud)

假设你不住在斐济,每次都会出错.你基本上说,"将我的当地时间,在其他一些区域转换为utc" - 这没有任何意义.

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

关于你的改变 - 确保你可以强制使用这种类型,并改变你正在做的事情的意义,这样才有意义.但你确定这是你想要的吗?.Kind手头的日期是什么时候?如果它还没有Unspecified,那么它带有一些意图.您应该回到这些数据的来源,并确保它符合您的期望.

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

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


Pra*_*Das 8

在此示例中,我已将本地时区转换为未指定的类型,因此使用“DateTime.SpecifyKind()”方法对我来说工作正常

DateTime.SpecifyKind(utc,DateTimeKind.Unspecified);

此方法创建一个新的 DateTime 对象,该对象与指定的 DateTime 具有相同的刻度数,但被指定为未指定的 DateTimeKind 类型。

公共静态日期时间 ConvertLocalDate(DateTime utc) {

        string id = ConfigurationManager.AppSettings["Timezone"].ToString();
        TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById(id);
        utc = DateTime.SpecifyKind(utc,DateTimeKind.Unspecified);
        DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(utc, cstZone);
        return cstTime;
    }
Run Code Online (Sandbox Code Playgroud)