- 
                Notifications
    
You must be signed in to change notification settings  - Fork 176
 
Open
Description
有按天、按周、按月、按年分表路由,缺少按季度的分表路由,我参照做了实现,请问有错误的地方吗?
/// <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
Labels
No labels