为什么我不能向 OffsetDateTime 添加月份?

Why can't I add months to OffsetDateTime?

我正在使用 NodaTime 管理 .Net Core WebApi 中的日期和时区。库中的一种类型是 OffsetDateTime,它与 .Net 框架中的 DateTimeOffset 非常相似。我到处都使用它以明确和透明的方式操作日期,因为日期有时会进入系统时区和用户时区。

我需要在某个时间点将一个月添加到某个日期,但我无法将一个月添加到 OffsetDateTime 对象,我所能做的就是添加到小时或称为 Duration 的类型,即日历-独立的。如果它是我能理解的 Instant 类型,因为 Instant 以一种非常抽象的方式表示一个时间点,而不是 OffsetDateTime。 OffsetDateTime 甚至有一个 "Calendar" 属性 这确实表明它绑定到一个日历系统,它应该允许你像我想做的那样做算术,而不必通过类型转换等。

最重要的是,DateTimeOffset(来自 .net 框架)允许您添加月份,但我希望保持一致并在所有地方使用相同的类型。

长话短说,我做不到:

public OffsetDateTime GetPreviousMonth(OffsetDateTime input)
{
    return input.AddMonths(-1)
}

我只能做:

offsetDateTime.PlusHours(15)
offsetDateTime.PlusMinutes(3000)
offsetDateTime.Minus(Duration.FromMinutes(60))
offsetDateTime.Minus(Duration.FromHours(1))

知道如何在不进行类型转换的情况下解决这个问题吗?也许我忽略了文档中的某些内容,但我不这么认为。

您可以使用 OffsetDateTime.With,它可以让您提供一个 LocalDate 调节器。您可以使用 PeriodLocalDate 上操作 (PlusMinus、...),它允许您以月为单位指定时间跨度:

public OffsetDateTime GetPreviousMonth(OffsetDateTime input)
{
    return input.With((LocalDate ld) => ld.Minus(Period.FromMonths(1)));
}

OffsetDateTime 表示与 UTC 有偏差的本地日期时间, 是 Instant。

但是,它没有绑定到时区。

因此,您可以从中添加一个“固定”数量,例如秒、分钟和小时,因为它们不依赖于时区。

您不能从中减去一个月,因为它不知道过去一个月是否有日光转换。

我知道您要求的是不进行类型转换的解决方案,但实际上您做不到。要正确处理此问题,您必须将其转换为具有正确时区的 ZonedDateTime。任何未指定时区的解决方案最终都可能会遇到结果错误的情况。

你可以直接使用OffsetDateTime,但是你应该使用一些类似now()的方法。 然后可以加减D,M,Y,H,M,S等等

OffsetDateTime.now().minusDays(5).
format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"))

OffsetDateTime.now(ZoneOffset.UTC).plusMonths(month).
                format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"))