using Cronos; using Mirea.Api.Endpoint.Configuration.Model.GeneralSettings; using System; using System.Collections.Generic; using System.Linq; namespace Mirea.Api.Endpoint.Common.Services; public static class CronUpdateSkipService { public static ScheduleSettings.CronUpdateSkip Get(this Dto.Common.CronUpdateSkip date) { if (date.Date.HasValue) return new ScheduleSettings.CronUpdateSkip(date.Date.Value); if (date is { Start: not null, End: not null }) return new ScheduleSettings.CronUpdateSkip(date.Start.Value, date.End.Value); throw new ArgumentException("It is impossible to create a structure because it has incorrect values."); } public static List Filter(this List data, DateOnly? currentDate = null) { currentDate ??= DateOnly.FromDateTime(DateTime.Now); return data.OrderBy(x => x.End ?? x.Date) .Where(x => x.Date == currentDate || (x.Start <= currentDate && x.End >= currentDate)) .ToList(); } public static List Filter(this List data, DateTime? currentDate = null) => data.Filter(DateOnly.FromDateTime(currentDate ?? DateTime.Now)); public static List GetNextTask(this List data, CronExpression expression, int depth = 1, DateOnly? currentDate = null) { if (depth <= 0) return []; currentDate ??= DateOnly.FromDateTime(DateTime.UtcNow); DateTimeOffset nextRunTime = currentDate.Value.ToDateTime(new TimeOnly(0, 0, 0)); List result = []; do { var lastSkip = data.Filter(nextRunTime.DateTime).LastOrDefault(); if (lastSkip is { Start: not null, End: not null }) nextRunTime = new DateTimeOffset(lastSkip.End.Value.AddDays(1), new TimeOnly(0, 0, 0), TimeSpan.Zero); else if (lastSkip.Date.HasValue) nextRunTime = new DateTimeOffset(lastSkip.Date.Value.AddDays(1), new TimeOnly(0, 0, 0), TimeSpan.Zero); var next = expression.GetNextOccurrence(nextRunTime, TimeZoneInfo.Local); if (!next.HasValue) return result; nextRunTime = next.Value; if (!data.Filter(nextRunTime.DateTime).Any()) continue; result.Add(nextRunTime); nextRunTime = nextRunTime.AddMinutes(1); } while (result.Count < depth); return result; } }