首页 .Net ABP 源码解析 九. 时间

ABP 源码解析 九. 时间


介绍

虽然有些应用程序以单一时区为目标,但其他应用程序则以许多不同时区为目标。为了满足这些需求并集中日期时间操作,ABP为日期时间操作提供了一个通用的基础结构。


UML

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 >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 >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 >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 >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)转换为本地时间也需要用此功能。


我的公众号
特别声明:本站部分内容收集于互联网是出于更直观传递信息的目的。该内容版权归原作者所有,并不代表本站赞同其观点和对其真实性负责。如该内容涉及任何第三方合法权利,请及时与824310991@qq.com联系,我们会及时反馈并处理完毕。