using System; using System.Threading; using System.Threading.Tasks; namespace StellaOps.AirGap.Time.Services; public sealed partial class TimeAnchorPolicyService { public async Task CalculateDriftAsync( string tenantId, DateTimeOffset targetTime, CancellationToken cancellationToken = default) { ArgumentException.ThrowIfNullOrWhiteSpace(tenantId); var now = _timeProvider.GetUtcNow(); var status = await _statusService.GetStatusAsync(tenantId, now, cancellationToken).ConfigureAwait(false); if (!status.HasAnchor) { return new TimeAnchorDriftResult( HasAnchor: false, Drift: TimeSpan.Zero, DriftExceedsThreshold: false, AnchorTime: null); } var drift = targetTime - status.Anchor!.AnchorTime; var absDriftSeconds = Math.Abs(drift.TotalSeconds); var exceedsThreshold = absDriftSeconds > _options.MaxDriftSeconds; return new TimeAnchorDriftResult( HasAnchor: true, Drift: drift, DriftExceedsThreshold: exceedsThreshold, AnchorTime: status.Anchor.AnchorTime); } }