问题描述
我需要设置这种视图模型的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;