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

Why is the DateTimeOffset.AddMonths(1).Date not the same as ((dto) => dto.AddMonths(1).Date)

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

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

例如,当我的单元测试试图验证一个月时:

    // 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上找不到解释...

看看DateTimeOffset.Date page on MSDN:

This property removes any significant part of the time component from a DateTimeOffset object and returns only its significant date component. For example, if the DateTimeOffset object has a date and time value of "1/12/07 4:01pm +7:30", the property returns a DateTime value of "1/12/07 12:00:00 AM". The DateTime value can then be displayed by using any of the standard or custom format specifiers that display dates only. (See the Example section for an illustration.)

The value of the DateTime.Kind property of the returned DateTime object is always DateTimeKind.Unspecified. It is not affected by the value of the Offset property.

另见 DateTimeOffset Constructor (DateTime) page on MSDN:

This constructor's behavior depends on the value of the DateTime.Kind property of the dateTime parameter:

  • If the value of DateTime.Kind is DateTimeKind.Utc, the DateTime property of the new instance is set equal to dateTime, and the Offset property is set equal to Zero.
  • If the value of DateTime.Kind is DateTimeKind.Local or DateTimeKind.Unspecified, the DateTime property of the new instance is set equal to dateTime, and the Offset property is set equal to the offset of the local system's current time zone.

因此,通过使用 Date 属性 转换为 DateTime,您删除了时间分量,但也删除了偏移量和 Kind.

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