2016-04-03 88 views
0

当种类为Utc时,将UTC中的DateTime转换为DateTimeOffset 时出错。 origDateTime来自webservice,所以我不能控制内容或格式。 在大多数情况下它与Kind = Unspecified(即使艰难的时间在Utc),然后它的工作,但在极少数情况下Kind = Utc,然后转换为DateTimeOffset引发异常: “UTC抵消Utc DateTime实例必须为0. \ r \ n参数名称:偏移量“ 我应该如何解决它?当种类为Utc时,从datetime UTC转换为datetimeoffset时出错

 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; 
     } 
+0

DATATIME解析使用时区设置,所以无需转换自动转换为UTC时间。与数据库的连接也自动使用UTC时间,所以你的代码没有多大意义。输入在另一时区收集的数据时或在另一时区显示时间时,仅使用时区偏移。网络库函数将时间存储在计算机中,以UTC的数字表示,并在输入或输出时自动转换UTC。 – jdweng

+0

我需要使用不同的时区(根据另一个字段)将每个日期时间转换为datetimeoffset,以便能够显示在不同的时区中。泽维尔回答解决了这个问题。谢谢。 – user2455595

回答

2

有几件事情:

  • 如果你真的需要切换DateTimeKind无需调整其价值,使用DateTime.SpecifyKind。它比处理蜱更清洁。但是,我不认为你真的需要这样做。

  • 请勿使用ToLocalTimeToUniversalTime。这两种方法都将在转换过程中使用服务器的时区设置。

  • 我不确定您的真的代码实际上是否解析字符串,因为您表示它来自数据库。如果它来自数据库,则不应涉及任何字符串解析。只要做到以下几点:

    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); 
    
+0

字符串的使用仅用于测试目的,与ToUniversalTime相同。 这只是模拟来自服务器的数据。 你能解释什么是我在构造函数中添加偏移量之间的差异DateTimeOffset localTime = new DateTimeOffset(origDateTime,localTimeZone.GetUtcOffset(origDateTime)); 和你的代码使用ConvertTime? – user2455595

+0

我看到了区别,你的代码真的把日期和修改为{4/2/2016 11:25:20 AM -07:00}根据定义我只需要做偏移量,否则我会使用你的代码的 。 谢谢。 – user2455595

+0

“DateTimeOffset”中的日期和时间是* local *时间,已经针对该偏移进行了调整。这不仅仅是一个.NET的东西 - 它是由ISO8601公约。时间戳“2016-04-02T18:25:20 + 00:00”相当于“2016-04-02T11:25:20-07:00”。如果您只是在不调整时间值的情况下应用偏移量,则实际上是指完全不同的时间点。 –

1

所以您的问题将得到解决,如果你一直设置你的DateTimeKindUnspecified,不是吗?

试试这个:

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; 
     } 
+1

这解决了这个问题。 谢谢。 – user2455595