如何使用NodaTime检查“现在”是否在两个OffsetDateTime对象之间?

问题描述

我需要设置这种视图模型的IsCurrent字段:

public class SessionVm {
    public OffsetDateTime StartTime { get; set; }
    public OffsetDateTime EndTime { get; set; }
    public string TimezoneId { get; set; }
    public bool IsCurrent {get;}
}

我认为我可以为IsCurrent字段编写这样的getter:

public bool IsCurrent
{
    get
    {
        var currentTimeWithOffset = new OffsetDateTime(LocalDateTime.FromDateTime(DateTime.UtcNow),StartTime.Offset);
        return StartTime < currentTimeWithOffset && currentTimeWithOffset < EndTime;
    }
}

但是,看来OffsetDateTime没有实现IComparable。然后,我发现LocalDateTime可以并尝试了此操作:

public bool IsCurrent
{
    get
    {
        var currentLocalDateTime = SystemClock.Instance.InUtc().GetCurrentLocalDateTime();
        var currentOffsetDateTime = new OffsetDateTime(currentLocalDateTime,StartTime.Offset);
        var currentLocalDateTimeExpectedWithOffsetAdded = currentOffsetDateTime.LocalDateTime;

        var startLocalDateTime = StartTime.LocalDateTime;
        var endLocalDateTime = StartTime.LocalDateTime;
        return startLocalDateTime < currentLocalDateTimeExpectedWithOffsetAdded && currentLocalDateTimeExpectedWithOffsetAdded < endLocalDateTime;
    }
}

但是,currentLocalDateTimeExpectedWithOffsetAdded并不能真正代表我的需求。在OffsetDateTime字段上方的LocalDateTime类文档中:

/// <summary>
/// Returns the local date and time represented within this offset date and time.
/// </summary>
/// <value>The local date and time represented within this offset date and time.</value>
public LocalDateTime LocalDateTime => new LocalDateTime(Date,TimeOfDay);

显然,我对这句话有误解,并认为这会使我的日期时间有偏差。
您能帮我弄清楚如何获取添加了偏移量的UTC日期时间对象吗?还是有更好的方法来实现IsCurrent字段? 预先谢谢你:)

解决方法

首先,我强烈建议完全删除DateTime.UtcNow的使用。而是使用NodaTime的IClock接口。与其他依赖项一样,使用SystemClock.Instance作为生产实现来注入。对于测试,您可以使用FakeClock软件包提供的NodaTime.Testing

一旦有时钟,请致电IClock.GetCurrentInstant()找出当前时刻。如果您确实要使用DateTime.UtcNow,可以致电Instant.FromDateTimeUtc(DateTime.UtcNow)。但是请注意,这是一种测试性强,NodaTime惯用的方法。

我会将您当前的OffsetDateTime值转换为瞬时值,然后可以执行比较:

public bool IsCurrent
{
    get
    {
        var startInstant = StartTime.ToInstant();
        var endInstant = EndTime.ToInstant();
        var now = clock.GetCurrentInstant();
        return startInstant <= now && now < endInstant;
    }
}

(或者,从两个瞬间创建一个Interval,然后使用Interval.Contains(Instant)。)

,

OffsetDateTime明确表示一个时刻,因此您可以ToInstant并将开始时刻和结束时刻与当前时刻进行比较。 Instant 是可比的。

Instant now = SystemClock.Instance.GetCurrentInstant();
Instant startInstant = StartTime.ToInstant();
Instant endInstant = EndTime.ToInstant();
return startInstant < now && now < endInstant;

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...