Created
November 27, 2017 09:00
-
-
Save bjcull/670fb744c5770dd10639b2f75367ecf0 to your computer and use it in GitHub Desktop.
The current time service I use to keep track of dates relative to a certain timezone.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TimeService : ITimeService | |
{ | |
private readonly ILogger _logger; | |
private Instant? _frozenTime; | |
private Instant _realTimeAtTimeOfFreezing = Instant.MinValue; | |
private readonly IDateTimeZoneProvider _timeZoneProvider = DateTimeZoneProviders.Tzdb; | |
private readonly DateTimeZone _timeZone; | |
public TimeService(ILogger logger, string systemTimeZone, DateTime? setDate = null) | |
{ | |
_logger = logger; | |
_timeZone = _timeZoneProvider[systemTimeZone]; | |
if (setDate.HasValue) | |
{ | |
if (setDate.Value.Kind != DateTimeKind.Utc) | |
{ | |
throw new ArgumentException("Supplied DateTime must have a Kind of UTC.", nameof(setDate)); | |
} | |
_frozenTime = Instant.FromDateTimeUtc(setDate.Value); | |
_logger.Warning("Time has been frozen to {currentTime}", _frozenTime.Value); | |
} | |
} | |
public void SetDateUtc(Instant date) | |
{ | |
_frozenTime = date; | |
_realTimeAtTimeOfFreezing = Instant.FromDateTimeUtc(DateTime.UtcNow); | |
_logger.Warning("Time has been frozen to {currentTime}", _frozenTime.Value); | |
} | |
public Instant UtcNow | |
{ | |
get | |
{ | |
if (_frozenTime.HasValue) | |
{ | |
return GetSlidingFrozenTime(); | |
} | |
return Instant.FromDateTimeUtc(DateTime.UtcNow); | |
} | |
} | |
public ZonedDateTime LocalNow | |
{ | |
get | |
{ | |
if (_frozenTime.HasValue) | |
{ | |
return GetSlidingFrozenTime().InZone(_timeZone); | |
} | |
return Instant.FromDateTimeUtc(DateTime.UtcNow).InZone(_timeZone); | |
} | |
} | |
public DateTime UtcNowDT => UtcNow.ToDateTimeUtc(); | |
public DateTime LocalNowDT => LocalNow.ToDateTimeUnspecified(); | |
public DateTime LocalTodayDT => LocalNow.Date.ToDateTimeUnspecified(); | |
public ZonedDateTime ParseAsSystemTimeZone(DateTime date) | |
{ | |
return _timeZone.AtLeniently(LocalDateTime.FromDateTime(date)); | |
} | |
public ZonedDateTime AtTime(ZonedDateTime date, LocalTime time) | |
{ | |
return _timeZone.AtLeniently(date.Date.At(time)); | |
} | |
public ZonedDateTime InTimezone(LocalDateTime date) | |
{ | |
return _timeZone.AtLeniently(date); | |
} | |
public ZonedDateTime InTimezone(Instant instant) | |
{ | |
return instant.InZone(_timeZone); | |
} | |
public bool IsTimeFrozen => _frozenTime.HasValue; | |
private Instant GetSlidingFrozenTime() | |
{ | |
if (!_frozenTime.HasValue) | |
{ | |
return Instant.MinValue; | |
} | |
return _frozenTime.Value.Plus(Instant.FromDateTimeUtc(DateTime.UtcNow) - _realTimeAtTimeOfFreezing); | |
} | |
public Instant ParseAsUtc(DateTime date) | |
{ | |
return Instant.FromDateTimeUtc(date); | |
} | |
public ZonedDateTime ParseAsUtcIntoTimezone(DateTime date) | |
{ | |
return ParseAsUtc(date).InZone(_timeZone); | |
} | |
public ZonedDateTime ParseDate(DateTime date) | |
{ | |
// Logic: | |
// -> If Kind.Local > ConvertToUtc > ConvertToSystemTimezone | |
// -> If Kind.Utc > ConvertToSystemTimezone | |
// -> If Kind.Unspecified (and else) > ParseAsSystemTimezone (sydney) | |
if (date.Kind == DateTimeKind.Local) | |
{ | |
return ParseAsUtcIntoTimezone(date.ToUniversalTime()); | |
} | |
if (date.Kind == DateTimeKind.Utc) | |
{ | |
return ParseAsUtcIntoTimezone(date); | |
} | |
return ParseAsSystemTimeZone(date); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment