This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
mfgames-nitride-cil/src/MfGames.Nitride.Temporal/TimeService.cs

123 lines
3.7 KiB
C#

using System;
using NodaTime;
using NodaTime.Testing;
namespace MfGames.Nitride.Temporal;
/// <summary>
/// A class that handles date and time processing. This provides identifying
/// the desire time zone along with various methods for processing parsed
/// DateTime objects into NodaTime.Instant.
/// </summary>
public class TimeService
{
public TimeService()
{
// We use FakeClock because we don't want time to advance in the
// middle of running, just in case we are just a few seconds before
// rollover.
Instant instant = SystemClock.Instance.GetCurrentInstant();
this.DateTimeZone = DateTimeZoneProviders.Bcl.GetSystemDefault();
this.Clock = new FakeClock(instant);
}
/// <summary>
/// Gets or sets the clock used to perform time calculations.
/// </summary>
public IClock Clock { get; set; }
/// <summary>
/// Gets or sets the date time zone used for processing.
/// </summary>
public DateTimeZone DateTimeZone { get; set; }
/// <summary>
/// Gets the instant when the files expire.
/// </summary>
public Instant? Expiration => this.Expires.HasValue
? this.Clock.GetCurrentInstant()
.Minus(Duration.FromTimeSpan(this.Expires.Value))
: null;
/// <summary>
/// Gets or sets the expiration time span, which is calculated from the
/// current time.
/// </summary>
public TimeSpan? Expires { get; set; }
/// <summary>
/// Creates an instant from a given year, month, and day.
/// </summary>
/// <param name="year">The numerical year.</param>
/// <param name="month">The numerical month.</param>
/// <param name="day">The numerical day of month.</param>
/// <returns>An instant in the clock's time zone.</returns>
public Instant CreateInstant(
int year,
int month,
int day)
{
var date = new LocalDate(year, month, day);
return this.CreateInstant(date);
}
/// <summary>
/// Creates an instant from the given local date.
/// </summary>
/// <param name="date">The date to parse.</param>
/// <returns>An instant in the clock's time zone.</returns>
public Instant CreateInstant(LocalDate date)
{
ZonedDateTime zoned = date.AtStartOfDayInZone(this.DateTimeZone);
var instant = zoned.ToInstant();
return instant;
}
/// <summary>
/// Creates an instant from the given date time zone.
/// </summary>
/// <param name="when">The object to convert.</param>
/// <returns>An instant representing this DateTimeOffset.</returns>
public Instant CreateInstant(DateTimeOffset when)
{
var offset = OffsetDateTime.FromDateTimeOffset(when);
return offset.ToInstant();
}
/// <summary>
/// Creates an instant from the given date time.
/// </summary>
/// <param name="when">The object to convert.</param>
/// <returns>An instant representing this DateTimeOffset.</returns>
public Instant CreateInstant(DateTime when)
{
if (when.Kind == DateTimeKind.Unspecified)
{
var localDate = LocalDate.FromDateTime(when);
return this.CreateInstant(localDate);
}
var offset = new DateTimeOffset(when);
return this.CreateInstant(offset);
}
/// <summary>
/// Converts an instant into a DateTime for the clock's time zone.
/// </summary>
/// <param name="instant">The instant to convert.</param>
/// <returns>A DateTime in the correct date and time.</returns>
public DateTime ToDateTime(Instant instant)
{
return instant.InZone(this.DateTimeZone)
.ToDateTimeOffset()
.DateTime;
}
}