Nodatime到最近间隔的舍入时间

问题描述 投票:2回答:1

我们需要将时间下限到最接近的任意间隔(例如,以“时间跨度”或“持续时间”表示。)>

假设我们需要将其下限到最近的十分钟。例如13:02变成13:00,而14:12变成14:10

无需使用Nodatime,您可以执行this:之类的操作>

// Floor
long ticks = date.Ticks / span.Ticks;
return new DateTime( ticks * span.Ticks );

将使用时间间隔的刻度将日期时间设置为特定时间。

似乎NodaTime暴露了一些我们之前未曾考虑过的复杂性。您可以编写如下函数:

public static Instant FloorBy(this Instant time, Duration duration)
=> time.Minus(Duration.FromTicks(time.ToUnixTimeTicks() % duration.BclCompatibleTicks));

但是该实现似乎并不正确。“最接近十分钟”似乎取决于时区/时间偏移。尽管在UTC时可能是13:02,在尼泊尔时偏移+05:45,但时间应该是18:47。

[这意味着在UTC中,到达最近的十分钟意味着减去两分钟,而在尼泊尔,则意味着减去七分钟。

我觉得我应该能够以某种方式将ZonedDateTime或OffsetDateTime取整。我可以通过编写像这样的函数来接近]

public static OffsetDateTime FloorToNearestTenMinutes(this OffsetDateTime time)
{
    return time
        .Minus(Duration.FromMinutes(time.Minute % 10))
        .Minus(Duration.FromSeconds(time.Second));
}

但是这不允许我指定任意持续时间,因为OffsetDateTime没有刻度的概念。

如何考虑到时区,以任意间隔正确舍入Instant / ZonedDateTime / OffsetDateTime?

我们需要将时间下限到最接近的任意间隔(例如,以“时间跨度”或“持续时间”表示)。举个例子,我们需要将其下限到最近的十分钟。例如13:02变成...

对于OffsetDateTime,我建议您编写一个Func<LocalTime, LocalTime>,它实际上是Noda Time术语中的“调节器”。然后,您可以只使用With方法:

// This could be a static field somewhere - or a method, so you can use
// a method group conversion.
Func<LocalTime, LocalTime> adjuster =>
    new LocalTime(time.Hour, time.Minute - time.Minute % 10, 0);

// The With method applies the adjuster to just the time portion,
// keeping the date and offset the same.
OffsetDateTime rounded = originalOffsetDateTime.With(adjuster);

请注意,这仅是因为您的舍入将永远不会更改日期。如果您需要一个可以更改日期的版本(例如,将23:58舍入到第二天的00:00),则需要获取新的LocalDateTime并使用该OffsetDateTime构造一个新的LocalDateTime和原始偏移量。我们没有方便的方法,但这只是调用构造函数的问题。

由于您给出的原因,

ZonedDateTime很难从根本上

棘手。目前,尼泊尔还没有遵守DST,但将来可能会这样做。在DST边界附近四舍五入可能会使您陷入歧义甚至跳过的时间。因此,我们没有为With提供类似的ZonedDateTime方法。 (就您而言,这是不可能的,尽管从历史上看……使用日期调节器很容易导致这种情况。)

您可以做的是:

  • 呼叫ZonedDateTime.ToOffsetDateTime
  • 如上环绕OffsetDateTime
  • 呼叫OffsetDateTime.InZone(zone)返回到ZonedDateTime
  • 可以然后,如果您想检测出奇怪的情况,请检查结果ZonedDateTime的偏移量是否与原始偏移量相同-但您需要决定如何实际处理它们。不过,这种行为是相当合理的-如果您以ZonedDateTime开头,且其时间部分为(例如)01:47,那么您将在7分钟前的同一时区以ZonedDateTime结尾。如果在最近7分钟内发生过渡,则不是[[可能,而是01:40 ...但是我可疑

您实际上不需要为此担心。
c# nodatime
1个回答
1
投票

对于OffsetDateTime,我建议您编写一个Func<LocalTime, LocalTime>,它实际上是Noda Time术语中的“调节器”。然后,您可以只使用With方法:

© www.soinside.com 2019 - 2024. All rights reserved.