介绍
虽然有些应用程序以单一时区为目标,但其他应用程序则以许多不同时区为目标。为了满足这些需求并集中日期时间操作,ABP为日期时间操作提供了一个通用的基础结构。
UML
- Clock:静态类,用于执行一些常见的日期时间操作
- IClockProvider: 定义接口来执行一些常见的日期时间操作
- UnspecifiedClockProvider: 未指明的Clock提供者
- LocalClockProvider: 使用本地时间实现Clock提供者
- UtcClockProvider: 使用UTC时间实现Clock提供者
- ClockProviders:静态类,提供三种常用的Clock提供者实例
源码解析
IClockProvider
/// <summary>
/// Defines interface to perform some common date-time operations.
/// 定义接口来执行一些常见的日期时间操作
/// </summary>
public interface IClockProvider
{
/// <summary>
/// Gets Now.
/// 获取当前时间
/// </summary>
DateTime Now { get; }
/// <summary>
/// Gets kind.
/// 获取日期种类
/// </summary>
DateTimeKind Kind { get; }
/// <summary>
/// Is that provider supports multiple time zone.
/// 是否支持多时区
/// </summary>
bool SupportsMultipleTimezone { get; }
/// <summary>
/// Normalizes given <see cref="DateTime"/>.
/// 标准化指定日期,将日期种类标准化为Kind 日期
/// </summary>
/// <param name="dateTime">DateTime to be normalized.
/// 要标准化的日期时间
/// </param>
/// <returns>Normalized DateTime.标准化后的日期</returns>
DateTime Normalize(DateTime dateTime);
}
UnspecifiedClockProvider
/// <summary>
/// 未指明的Clock提供者
/// </summary>
public class UnspecifiedClockProvider : IClockProvider
{
public DateTime Now => DateTime.Now;
public DateTimeKind Kind => DateTimeKind.Unspecified;
public bool SupportsMultipleTimezone => false;
public DateTime Normalize(DateTime dateTime)
{
return dateTime;
}
internal UnspecifiedClockProvider()
{
}
}
UtcClockProvider
/// <summary>
/// Implements <see cref="IClockProvider"/> to work with UTC times.
/// 使用UTC时间实现<see cref="IClockProvider"/>
/// </summary>
public class UtcClockProvider : IClockProvider
{
public DateTime Now => DateTime.UtcNow;
public DateTimeKind Kind => DateTimeKind.Utc;
public bool SupportsMultipleTimezone => true;
public DateTime Normalize(DateTime dateTime)
{
if (dateTime.Kind == DateTimeKind.Unspecified)
{
return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
}
if (dateTime.Kind == DateTimeKind.Local)
{
return dateTime.ToUniversalTime();
}
return dateTime;
}
internal UtcClockProvider()
{
}
}
LocalClockProvider
/// <summary>
/// Implements <see cref="IClockProvider"/> to work with local times.
/// 使用本地时间实现<see cref="IClockProvider"/>
/// </summary>
public class LocalClockProvider : IClockProvider
{
public DateTime Now => DateTime.Now;
public DateTimeKind Kind => DateTimeKind.Local;
public bool SupportsMultipleTimezone => false;
public DateTime Normalize(DateTime dateTime)
{
if (dateTime.Kind == DateTimeKind.Unspecified)
{
return DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
}
if (dateTime.Kind == DateTimeKind.Utc)
{
return dateTime.ToLocalTime();
}
return dateTime;
}
internal LocalClockProvider()
{
}
}
Clock
/// <summary>
/// Used to perform some common date-time operations.
/// 用于执行一些常见的日期时间操作
/// </summary>
public static class Clock
{
/// <summary>
/// This object is used to perform all <see cref="Clock"/> operations.
/// Default value: <see cref="UnspecifiedClockProvider"/>.
/// 使用所有<see cref="Clock"/>操作
/// 默认值:<see cref="UnspecifiedClockProvider"/>
/// </summary>
public static IClockProvider Provider
{
get { return _provider; }
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value), "Can not set Clock.Provider to null!");
}
_provider = value;
}
}
private static IClockProvider _provider;
static Clock()
{
Provider = ClockProviders.Unspecified;
}
/// <summary>
/// Gets Now using current <see cref="Provider"/>.
/// </summary>
public static DateTime Now => Provider.Now;
public static DateTimeKind Kind => Provider.Kind;
/// <summary>
/// Returns true if multiple timezone is supported, returns false if not.
/// 如果支持多个时区,则返回true;反之则返回false
/// </summary>
public static bool SupportsMultipleTimezone => Provider.SupportsMultipleTimezone;
/// <summary>
/// Normalizes given <see cref="DateTime"/> using current <see cref="Provider"/>.
/// </summary>
/// <param name="dateTime">DateTime to be normalized.</param>
/// <returns>Normalized DateTime</returns>
public static DateTime Normalize(DateTime dateTime)
{
return Provider.Normalize(dateTime);
}
}
总结
ABP对于时间(Clock)的封装,主要是封装不同的 DateTimeKind 之间的日期格式化问题,比如,前端传入的是本地时间(时区为8),后端统一存储为utc的时候需要用到,后端将时间(UTC)转换为本地时间也需要用此功能。