Reputation: 989
I need to set IsCurrent
field of such a view model:
public class SessionVm {
public OffsetDateTime StartTime { get; set; }
public OffsetDateTime EndTime { get; set; }
public string TimezoneId { get; set; }
public bool IsCurrent {get;}
}
I thought I can write such a getter for the IsCurrent
field:
public bool IsCurrent
{
get
{
var currentTimeWithOffset = new OffsetDateTime(LocalDateTime.FromDateTime(DateTime.UtcNow), StartTime.Offset);
return StartTime < currentTimeWithOffset && currentTimeWithOffset < EndTime;
}
}
However, it looks like OffsetDateTime
doesn't implement IComparable
. Then I found that LocalDateTime
does and tried this:
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;
}
}
However, currentLocalDateTimeExpectedWithOffsetAdded
doesn't really represent what I need. From the OffsetDateTime
class documentation above the LocalDateTime
field:
/// <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);
Apparently, I misunderstood the sentence and thought that it would give me the datetime with an offset.
Could you help me to figure out how can I get the datetime object that would be UTC with added offset? Or maybe there is a better way to implement IsCurrent
field?
Thank you in advance :)
Upvotes: 0
Views: 463
Reputation: 271735
OffsetDateTime
s unambiguously represent an instant in time, so you can ToInstant
and compare the start and end instants with the current instant. Instant
s are comparable.
Instant now = SystemClock.Instance.GetCurrentInstant();
Instant startInstant = StartTime.ToInstant();
Instant endInstant = EndTime.ToInstant();
return startInstant < now && now < endInstant;
Upvotes: 1
Reputation: 1500785
Firstly, I'd strongly suggest removing the use of DateTime.UtcNow
entirely. Instead, use the IClock
interface that's part of NodaTime. Inject that as you would any other dependency, using SystemClock.Instance
as the production implementation. For tests, you can use a FakeClock
as provided by the NodaTime.Testing
package.
Once you've got a clock, call IClock.GetCurrentInstant()
to find out the current instant. If you really, really want to use DateTime.UtcNow
, you can call Instant.FromDateTimeUtc(DateTime.UtcNow)
. But be aware that this is a much less testable, and less NodaTime-idiomatic approach.
I'd convert your current OffsetDateTime
values to a instants, then you can perform the comparison:
public bool IsCurrent
{
get
{
var startInstant = StartTime.ToInstant();
var endInstant = EndTime.ToInstant();
var now = clock.GetCurrentInstant();
return startInstant <= now && now < endInstant;
}
}
(Alternatively, create an Interval
from the two instants, and use Interval.Contains(Instant)
.)
Upvotes: 2