为什么DateTimeOffset.AddMonths(1).Date与((dto)=> dto.AddMonths(1).Date不一样)

时间:2017-03-26 20:08:57

标签: c# date datetimeoffset

我在域逻辑中有一个辅助函数:

private static DateTimeOffset CalculateNextDate(DateTimeOffset previousDate, TimeUnit timeUnit, int quantity)
{
    Func<int, DateTimeOffset, DateTimeOffset> calcMethod;
    switch (timeUnit)
    {
        case TimeUnit.Month:
            calcMethod = (i, offset) => offset.AddMonths(i);
            break;
        // ... [irrelevant] ...
        default:
        // ... [irrelevant] ...
    }
    return calcMethod(quantity, previousDate).Date;
}

当我的unittest试图验证一个月时,例如:

    // Arrange
    int monthsToAdd = 1;
    var timeUnit = TimeUnit.Month;
    var sut = new TimeInterval(timeUnit, monthsToAdd);
    var now = DateTimeOffset.Now;

    // Act
   var result = sut.NextDate(now);

    // Assert
     var expectedDate = now.AddMonths(1).Date;
    Assert.AreEqual(expectedDate, result);  // FAILS

断言失败,因为expectedDate为{26/04/2017 0:00:00}而结果为{26/04/2017 0:00:00 +02:00}

我不明白为什么一个人可以保留偏移而另一个人放弃它。是因为我将.Date转换为DateTimeOffset吗?无法在msdn ...

上找到解释

1 个答案:

答案 0 :(得分:2)

查看https://personal.vanguard.com/us/funds/annuities/variable

  

此属性从DateTimeOffset对象中删除时间组件的任何重要部分,并仅返回其重要日期组件。 例如,如果DateTimeOffset对象的日期和时间值为“1/12/07 4:01 pm +7:30”,则该属性返回DateTime值“1/12/07 12:00:00 AM“即可。然后,可以使用仅显示日期的任何标准或自定义格式说明符来显示DateTime值。 (有关说明,请参阅示例部分。)

     

返回的DateTime对象的DateTime.Kind属性的值始终为DateTimeKind.Unspecified。它不受Offset属性值的影响。

另请参阅https://personal.vanguard.com/us/funds/tools/pricehistorysearch?radio=1&results=get&FundType=VVAP&FundIntExt=INT&FundId=0064&fundName=0064&fundValue=0064&radiobutton2=1&beginDate=03%2F01%2F2017&endDate=12%2F31%2F2017&year=#res

  

此构造函数的行为取决于dateTime参数的DateTime.Kind属性的值:

     
      
  • 如果DateTime.Kind的值为DateTimeKind.Utc,则将新实例的DateTime属性设置为dateTime,并将Offset属性设置为零。
  •   
  • 如果DateTime.Kind的值为DateTimeKind.Local或DateTimeKind.Unspecified,则将新实例的DateTime属性设置为dateTime,并将Offset属性设置为等于本地系统当前的偏移量时区。
  •   

因此,通过使用DateTime属性转换为Date,您可以删除时间组件,但也可以删除偏移量Kind

当您从DateTimeOffset转换为DateTime然后隐式转回DateTimeOffset时,它会假定这是当前时区的时间。