diff --git a/PARR.DAL/TransformServices/EsppScheduleTransformService.cs b/PARR.DAL/TransformServices/EsppScheduleTransformService.cs index 7c871a8f..9d61788e 100644 --- a/PARR.DAL/TransformServices/EsppScheduleTransformService.cs +++ b/PARR.DAL/TransformServices/EsppScheduleTransformService.cs @@ -1,4 +1,5 @@ using Microsoft.Extensions.Logging; +using PARR.DAL.Contracts; using PARR.DAL.DomainModels; using PARR.DAL.Services.Interfaces; @@ -9,6 +10,41 @@ namespace PARR.DAL.TransformServices private readonly IEsppSchTypeConfigService esppSchTypeConfigService; private readonly ILogger logger; + private readonly Dictionary monthDict = new Dictionary() + { + { "Январь", 1 }, + { "Февраль", 2 }, + { "Март", 3 }, + { "Апрель", 4 }, + { "Май", 5 }, + { "Июнь", 6 }, + { "Июль", 7 }, + { "Август", 8 }, + { "Сентябрь", 9 }, + { "Октябрь", 10 }, + { "Ноябрь", 11 }, + { "Декабрь", 12 } + }; + + private readonly Dictionary orderDict = new Dictionary() + { + { "Первый", 1 }, + { "Второй", 2 }, + { "Третий", 3 }, + { "Четвертый", 4 }, + { "Последний", 5 } + }; + + private readonly Dictionary dwDict = new Dictionary() + { + {"Понедельник", 1 }, + {"Вторник", 2 }, + {"Среда", 3 }, + {"Четверг", 4 }, + {"Пятница", 5 }, + {"Суббота", 6 }, + {"Воскресенье", 0 } + }; public EsppScheduleTransformService(IEsppSchTypeConfigService esppSchTypeConfigService, ILogger logger) { this.esppSchTypeConfigService = esppSchTypeConfigService; @@ -19,13 +55,31 @@ namespace PARR.DAL.TransformServices public DateTimeOffset GetNextDate(EsppScheduleDto esppSchedule, DateTimeOffset lastRun) { //todo: - - return lastRun; + //если больше текущего вернуть lastRun. Это и есть следующая дата + if (lastRun > DateTimeOffset.UtcNow) + return lastRun; + switch (esppSchedule.TypeSchedule.Id) + { + case (int)EsppSchTypeScheduleEnum.Regularly: + return GetNextDateRegularly(esppSchedule.Values, lastRun); + case (int)EsppSchTypeScheduleEnum.Weekly: + return GetNextDateWeekly(esppSchedule.Values, lastRun); + case (int)EsppSchTypeScheduleEnum.Monthly: + return GetNextDateMonthly(esppSchedule.Values, lastRun); + case (int)EsppSchTypeScheduleEnum.Monthly2: + return GetNextDateMonthly2(esppSchedule.Values, lastRun); + case (int)EsppSchTypeScheduleEnum.Annually: + return GetNextDateAnnually(esppSchedule.Values, lastRun); + case (int)EsppSchTypeScheduleEnum.Annually2: + return GetNextDateAnnually2(esppSchedule.Values, lastRun); + } + return lastRun;//todo убрать lastrun должен возвращать реальный результат } public List GetNextSchedule(EsppScheduleDto esppSchedule, DateTimeOffset lastRun) { + // расписание на оставшееся на сегодня время. его так мало... var schedules = new List(); //todo: @@ -60,5 +114,174 @@ namespace PARR.DAL.TransformServices return esppSchedule; } + + private DateTimeOffset GetNextDateRegularly(List values, DateTimeOffset lastRun) + { + var regDict = new Dictionary + { + {"Каждые 1 часа",1}, + {"Каждые 2 часа",2}, + {"Каждые 3 часа", 3}, + {"Каждые 4 часа", 4}, + {"Каждые 6 часов", 6}, + {"Каждые 12 часов", 12}, + {"Ежедневно", 24}, + {"Каждые 72 часа", 72}, + {"Каждые 96 часов", 96}, + {"Каждые 2 недели", 336}, + {"Каждые 60 дней", 1440}, + {"Каждые 80 дней", 1920}, + {"Каждые 90 дней", 2160}, + {"Каждые полгода", 4380}, + {"Каждые 1,5 года", 13140}, + {"Каждые 3 года", 26280}, + + }; + + var regNum = regDict[values[0].Value.Value]; + + var calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, DateTimeOffset.UtcNow.Day, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset); + //TODO: вот это повторяется от метода к методу + //Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию + if (calcDay < DateTimeOffset.UtcNow) + { + calcDay = calcDay.AddHours(regNum); + calcDay = GetNextDateRegularly(values, calcDay); + } + + return calcDay; + } + + private DateTimeOffset GetNextDateWeekly(List values, DateTimeOffset lastRun) + { + var dwNum = dwDict[values[0].Value.Value]; + + var calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, DateTimeOffset.UtcNow.Day, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset); + + if (((int)calcDay.DayOfWeek) != dwNum) + OffsetToDayOfWeek(dwNum, ref calcDay); + + //TODO: вот это повторяется от метода к методу + //Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию + if (calcDay < DateTimeOffset.UtcNow) + calcDay = calcDay.AddDays(7);//а вот тут что-то новенькое + + return calcDay; + } + + private DateTimeOffset GetNextDateMonthly(List values, DateTimeOffset lastRun) + { + int.TryParse(values[1].Value.Value, out int dayNum); + + var calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, dayNum, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset); + + //TODO: вот это повторяется от метода к методу + //Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию + if (calcDay < DateTimeOffset.UtcNow) + calcDay = calcDay.AddMonths(1);//и вот тут что-то новенькое + + return calcDay; + } + + private DateTimeOffset GetNextDateMonthly2(List values, DateTimeOffset lastRun) + { + var orderNum = orderDict[values[0].Value.Value]; + var dwNum = dwDict[values[1].Value.Value]; + + var calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, 1, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset); + + List daysList = FindAllDaysInMonth(dwNum, ref calcDay); + + if (orderNum == 5)//5-последний + calcDay = daysList.Last(); + else + calcDay = daysList[orderNum - 1]; + + //TODO: вот это повторяется от метода к методу + //Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию + if (calcDay < DateTimeOffset.UtcNow) + calcDay = GetNextDateAnnually2(values, calcDay); + + return calcDay; + } + private DateTimeOffset GetNextDateAnnually(List values, DateTimeOffset lastRun) + { + var monthNum = monthDict[values[0].Value.Value]; + int.TryParse(values[1].Value.Value, out int dayNum); + + var calcDay = new DateTimeOffset(lastRun.Year + 1, monthNum, dayNum, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset); + + //TODO: вот это повторяется от метода к методу + //Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию + if (calcDay < DateTimeOffset.UtcNow) + calcDay = GetNextDateAnnually(values, calcDay); + + return calcDay; + } + + private DateTimeOffset GetNextDateAnnually2(List values, DateTimeOffset lastRun) + { + var monthADict = new Dictionary + { + { "Января", 1 }, + { "Февраля", 2 }, + { "Марта", 3 }, + { "Апреля", 4 }, + { "Мая", 5 }, + { "Июня", 6 }, + { "Июля", 7 }, + { "Августа", 8 }, + { "Сентября", 9 }, + { "Октября", 10 }, + { "Ноября", 11 }, + { "Декабря", 12 } + }; + + var monthNum = monthADict[values[2].Value.Value]; + var orderNum = orderDict[values[0].Value.Value]; + var dwNum = dwDict[values[1].Value.Value]; + + var calcDay = new DateTimeOffset(lastRun.Year + 1, monthNum, 1, lastRun.Hour, lastRun.Minute, lastRun.Second, lastRun.Offset); + + List daysList = FindAllDaysInMonth(dwNum, ref calcDay); + + if (orderNum == 5)//5-последний + calcDay = daysList.Last(); + else + calcDay = daysList[orderNum]; + + //TODO: вот это повторяется от метода к методу + //Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию + if (calcDay < DateTimeOffset.UtcNow) + calcDay = GetNextDateAnnually2(values, calcDay); + + return calcDay; + } + + private List FindAllDaysInMonth(int dwNum, ref DateTimeOffset calcDay) + { + if (((int)calcDay.DayOfWeek) != dwNum) + OffsetToDayOfWeek(dwNum, ref calcDay); + + var daysList = new List(); + var monthNum = calcDay.Month; + while (calcDay.Month == monthNum) + { + daysList.Add(calcDay); + calcDay = calcDay.AddDays(7); + } + + return daysList; + } + + private void OffsetToDayOfWeek(int dwNum, ref DateTimeOffset calcDay) + { + var daysOffset = dwNum - ((int)calcDay.DayOfWeek); + + if (daysOffset < 0) + daysOffset = 7 + daysOffset; + + calcDay = calcDay.AddDays(daysOffset); + } } }