namespace JSMR.Infrastructure.Common.Time; public abstract class TimeProvider : ITimeProvider { protected abstract string Id { get; } protected abstract string[] TimeZoneIds { get; } private readonly IClock _clock; private readonly TimeZoneInfo _timeZone; public TimeProvider(IClock clock) { _clock = clock; _timeZone = ResolveTimeZone(); } private TimeZoneInfo ResolveTimeZone() { foreach (string timeZoneId in TimeZoneIds) { if (TimeZoneInfo.TryFindSystemTimeZoneById(timeZoneId, out TimeZoneInfo? timeZoneInfo)) return timeZoneInfo; } throw new TimeZoneNotFoundException($"Unable to resolve time zone for: {Id} ({string.Join(" / ", TimeZoneIds)})"); } public DateTimeOffset Now() => TimeZoneInfo.ConvertTime(_clock.UtcNow, _timeZone); public DateTimeOffset Local(DateTimeOffset offset) => TimeZoneInfo.ConvertTime(offset, _timeZone); public DateTimeOffset Local(int year, int month, int day, int hour) { DateTime local = new(year, month, day, hour, 0, 0, DateTimeKind.Unspecified); TimeSpan offset = _timeZone.GetUtcOffset(local); return new DateTimeOffset(local, offset); } }