Skip to content

添加按季度分表的路由 #291

@LEIRONGHUA

Description

@LEIRONGHUA

有按天、按周、按月、按年分表路由,缺少按季度的分表路由,我参照做了实现,请问有错误的地方吗?

/// <summary>
    /// 按季度分表的虚拟表路由
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public abstract class
        AbstractSimpleShardingQuarterKeyDateTimeVirtualTableRoute<TEntity> :
        AbstractSimpleShardingMonthKeyDateTimeVirtualTableRoute<TEntity>
        where TEntity : class
    {
        /// <summary>
        /// 提前创建表,补全之前的季度表
        /// </summary>
        /// <returns></returns>
        /// <exception cref="ArgumentException"></exception>
        protected override List<string> CalcTailsOnStart()
        {
            var beginTime = GetBeginTime();
            var currentQuarterStart = DateTime.Now.GetQuarterStartDate();

            if (beginTime > currentQuarterStart)
                throw new ArgumentException("Begin time cannot be after the current quarter start.");

            var tails = new List<string>();
            var current = beginTime;

            while (current <= currentQuarterStart)
            {
                tails.Add(TimeFormatToTail(current));
                current = current.GetNextQuarterStartDate(); // Move to the next quarter
            }

            return tails;
        }

        protected override string TimeFormatToTail(DateTime time)
        {
            return $"{time:yyyy}Q{time.GetQuarter()}";
        }

        public override Func<string, bool> GetRouteToFilter(DateTime shardingKey, ShardingOperatorEnum shardingOperator)
        {
            var t = TimeFormatToTail(shardingKey);

            switch (shardingOperator)
            {
                case ShardingOperatorEnum.GreaterThan:
                case ShardingOperatorEnum.GreaterThanOrEqual:
                    return tail => String.Compare(tail, t, StringComparison.Ordinal) >= 0;
                case ShardingOperatorEnum.LessThan:
                {
                    var currentQuarter = shardingKey.GetQuarterStartDate();
                    //处于临界值 o=>o.time < [2021-01-01 00:00:00] 尾巴20210101不应该被返回
                    if (currentQuarter == shardingKey)
                        return tail => String.Compare(tail, t, StringComparison.Ordinal) < 0;
                    return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0;
                }
                case ShardingOperatorEnum.LessThanOrEqual:
                    return tail => String.Compare(tail, t, StringComparison.Ordinal) <= 0;
                case ShardingOperatorEnum.Equal: return tail => tail == t;
                default:
                {
#if DEBUG
                    Console.WriteLine($"shardingOperator is not equal scan all table tail");
#endif
                    return tail => true;
                }
            }
        }

        /// <summary>
        /// 在几时执行创建对应的表
        /// </summary>
        /// <returns></returns>
        public override string[] GetCronExpressions()
        {
            return
            [
                "0 59 23 31 3 ?", // 3月31日23:59执行
                "0 59 23 30 6 ?", // 6月30日23:59执行
                "0 59 23 30 9 ?", // 9月30日23:59执行
                "0 59 23 31 12 ?", // 12月31日23:59执行
                "0 0 0 1 1,4,7,10 ?", // 每季度的第一天0点执行
                "0 1 0 1 1,4,7,10 ?" // 每季度的第一天1点执行
            ];
        }

        public override string[] GetJobCronExpressions()
        {
            return GetCronExpressions().Concat([
                "0 0 0 1 1,4,7,10 ?" // 每季度的第一天0点执行
            ]).Distinct().ToArray();
        }
    }
public static class DateTimeExtensions
{
    /// <summary>
    /// 获取日期所在的季度
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static int GetQuarter(this DateTime date)
    {
        return (date.Month - 1) / 3 + 1;
    }
    
    /// <summary>
    /// 获取季度的开始日期
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetQuarterStartDate(this DateTime date)
    {
        int quarter = date.GetQuarter();
        int startMonth = (quarter - 1) * 3 + 1; // 季度首月(1/4/7/10月)
        return new DateTime(date.Year, startMonth, 1);
    }
    
    /// <summary>
    /// 获取季度的结束日期
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetQuarterEndDate(this DateTime date)
    {
        DateTime start = date.GetQuarterStartDate();
        return start.AddMonths(3).AddDays(-1); // 下一季度首日前一天
    }
    
    /// <summary>
    /// 获取下一个季度的开始日期
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    public static DateTime GetNextQuarterStartDate(this DateTime date)
    {
        // int nextQuarter = date.GetQuarter() % 4 + 1; // 下一个季度
        // int startMonth = (nextQuarter - 1) * 3 + 1; // 下一个季度首月(1/4/7/10月)
        // return new DateTime(date.Year + (nextQuarter == 1 ? 1 : 0), startMonth, 1);
        var start = date.GetQuarterStartDate();
        return start.AddMonths(3); // 下一个季度首月
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions