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 FilterDateEntry(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 FilterDateEntry(this List data, DateTime? currentDate = null) => data.FilterDateEntry(DateOnly.FromDateTime(currentDate ?? DateTime.Now)); public static List Filter(this List data, DateOnly? currentDate = null) { currentDate ??= DateOnly.FromDateTime(DateTime.Now); return data.Where(x => x.Date >= currentDate || x.End >= currentDate) .OrderBy(x => x.End ?? x.Date) .ToList(); } public static List GetNextTask(this List data, CronExpression expression, int depth = 1, DateOnly? currentDate = null) { if (depth <= 0) return []; DateTimeOffset nextRunTime = (currentDate?.ToDateTime(TimeOnly.MinValue) ?? DateTime.Now).ToUniversalTime(); List result = []; do { var lastSkippedEntry = data.FilterDateEntry(nextRunTime.DateTime).LastOrDefault(); if (lastSkippedEntry is { Start: not null, End: not null }) nextRunTime = lastSkippedEntry.End.Value.ToDateTime(TimeOnly.MinValue).AddDays(1); else if (lastSkippedEntry.Date.HasValue) nextRunTime = lastSkippedEntry.Date.Value.ToDateTime(TimeOnly.MinValue).AddDays(1); var nextOccurrence = expression.GetNextOccurrence(nextRunTime.AddMinutes(-1), TimeZoneInfo.Local); if (!nextOccurrence.HasValue) return result; if (data.FilterDateEntry(nextOccurrence.Value.DateTime).Count != 0) { nextRunTime = nextOccurrence.Value.AddDays(1); continue; } result.Add(nextOccurrence.Value.ToLocalTime()); nextRunTime = nextOccurrence.Value.AddMinutes(1); } while (result.Count < depth); return result; } }