using Microsoft.Extensions.Logging; using PARR.BLL.Services.Interfaces; using PARR.Common; using PARR.Domain.Enums; namespace PARR.BLL.Services.Implementations { internal class CalendarService : ICalendarService { // !!! Вообще не использовать этот класс!!! Удалить его!!! Есть же INextRunServiceV2, вот его и использовать!!! private readonly ILogger logger; public CalendarService(ILogger logger) { this.logger = logger; } public DateOnly GetEndPeriodDate(DateOnly startPeriod, DistributionPeriodTypeEnum periodType, string distributionPeriod) { switch (periodType) { case (DistributionPeriodTypeEnum.Day): return startPeriod.AddDays(ParseInt(distributionPeriod)).AddDays(-1); case (DistributionPeriodTypeEnum.Month): return startPeriod.AddMonths(ParseInt(distributionPeriod)).AddDays(-1); case (DistributionPeriodTypeEnum.Year): return startPeriod.AddYears(ParseInt(distributionPeriod)).AddDays(-1); } return startPeriod; } private int ParseInt(string value) { try { return int.Parse(value); } catch (Exception ex) { logger.LogError(ex, $"{nameof(CalendarService)}, получение конца периода. Не смог распарсить string в int для значения {value}."); return 0; } } /// /// Возвращает список рабочих дней с начала периода без выходных /// /// /// /// /// /// /// public List GetWorkDatesForPeriod(DateOnly startPeriod, TimeOnly refTime, DistributionPeriodTypeEnum periodType, string distributionPeriod, GetWeekendsDelegate getWeekends) { var endPeriod = GetEndPeriodDate(startPeriod, periodType, distributionPeriod); //не получилось сделать асинхронным var weekends = getWeekends.Invoke(startPeriod, endPeriod).ToList(); //.ToListAsync(); //Берем список дат за период var workDays = GetDatesForPeriod(startPeriod, endPeriod); //Убираем праздники if (weekends.Any()) workDays = workDays.Where(t => !weekends.Any(x => x == t)).ToList(); //РАСКОММЕНТИРОВАТЬ НИЖЕ (28 дней), если не использовать календарь выходных дней ////Убираем числа старше 28, чтобы сравнять продолжительность с февралем //workDays.RemoveAll(t => t.Day > 28); //Так как в базе всё храним в UTC то время с 21 часа уже соответствует следующими суткам в календаре Москвы //просто сдвигаем на день весь список //if (refTime.Hour > 21) if (DateResolver.IsCurrentDayRelativeMskTime(refTime.Hour) == false) return workDays.Select(wd => wd.AddDays(-1)).ToList(); //иначе просто отдаём как есть return workDays; } /// /// Возвращает список дней между датами /// /// /// /// public List GetDatesForPeriod(DateOnly startPeriod, DateOnly endPeriod) { var workDaysList = new List(); var currentDay = startPeriod; while (currentDay <= endPeriod) { workDaysList.Add(currentDay); currentDay = currentDay.AddDays(1); } return workDaysList.OrderBy(t => t).ToList(); } /// /// Возвращает список дней между датами /// /// /// /// public List GetDatesForPeriod(DateTimeOffset startPeriod, DateTimeOffset endPeriod) { return GetDatesForPeriod(DateOnly.FromDateTime(startPeriod.DateTime), DateOnly.FromDateTime(endPeriod.DateTime)); } public DateTimeOffset GetDateWithTimeZoneOffset(DateTimeOffset date, int timeZoneOffsetHours) { return date.AddHours(timeZoneOffsetHours); } } }