using System.Diagnostics;
namespace System;
#if NETFRAMEWORK || NETSTANDARD || NETCOREAPP3_1 || NET5_0 || NET6_0 || NET7_0
/// <summary>提供时间的抽象</summary>
public abstract class TimeProvider
{
private sealed class SystemTimeProvider : TimeProvider
{
internal SystemTimeProvider() { }
}
private static readonly Int64 s_minDateTicks = DateTime.MinValue.Ticks;
private static readonly Int64 s_maxDateTicks = DateTime.MaxValue.Ticks;
/// <summary>获取一个 TimeProvider ,它提供基于 UtcNow的时钟、基于 的 Local时区、基于 的 Stopwatch高性能时间戳和基于 的 Timer计时器。</summary>
public static TimeProvider System { get; set; } = new SystemTimeProvider();
/// <summary>根据此 TimeProvider的时间概念获取本地时区。</summary>
public virtual TimeZoneInfo LocalTimeZone => TimeZoneInfo.Local;
/// <summary>获取 的频率 GetTimestamp() 作为每秒时钟周期数。</summary>
public virtual Int64 TimestampFrequency => Stopwatch.Frequency;
/// <summary>根据此 TimeProvider的时间概念,获取当前协调世界时 (UTC) 日期和时间,偏移量为零。</summary>
/// <returns></returns>
public virtual DateTimeOffset GetUtcNow() => DateTimeOffset.UtcNow;
/// <summary>根据基于 TimeProvider的时间概念 GetUtcNow()获取当前日期和时间,偏移量设置为 LocalTimeZone与协调世界时 (UTC) 的偏移量。</summary>
/// <returns></returns>
public DateTimeOffset GetLocalNow()
{
var utcNow = GetUtcNow();
var localTimeZone = LocalTimeZone ?? throw new ArgumentNullException(nameof(LocalTimeZone));
var utcOffset = localTimeZone.GetUtcOffset(utcNow);
if (utcOffset.Ticks == 0L) return utcNow;
var num = utcNow.Ticks + utcOffset.Ticks;
if ((UInt64)num > (UInt64)s_maxDateTicks)
num = ((num < s_minDateTicks) ? s_minDateTicks : s_maxDateTicks);
return new DateTimeOffset(num, utcOffset);
}
/// <summary>获取当前高频值,该值旨在测量计时器机制中精度较高的小时间间隔。</summary>
/// <returns></returns>
public virtual Int64 GetTimestamp() => Stopwatch.GetTimestamp();
/// <summary>获取使用 GetTimestamp()检索到的两个时间戳之间的已用时间。</summary>
/// <param name="startingTimestamp"></param>
/// <param name="endingTimestamp"></param>
/// <returns></returns>
public TimeSpan GetElapsedTime(Int64 startingTimestamp, Int64 endingTimestamp)
{
var timestampFrequency = TimestampFrequency;
if (timestampFrequency <= 0) throw new ArgumentOutOfRangeException(nameof(TimestampFrequency));
return new TimeSpan((Int64)((endingTimestamp - startingTimestamp) * (10000000.0 / timestampFrequency)));
}
/// <summary>获取自使用 GetTimestamp()检索值以来startingTimestamp的运行时间。</summary>
/// <param name="startingTimestamp"></param>
/// <returns></returns>
public TimeSpan GetElapsedTime(Int64 startingTimestamp) => GetElapsedTime(startingTimestamp, GetTimestamp());
}
#endif
|