using Microsoft.Extensions.Logging; using PARR.BLL.Services.Interfaces; using PARR.Constants; namespace PARR.BLL.Services.Implementations { internal class CalendarService : ICalendarService { private readonly ILogger logger; public CalendarService(ILogger logger) { this.logger = logger; } private 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; } } //private TimeSpan ParseTimeSpan(string value) //{ // try // { // return TimeSpan.Parse(value); // } // catch (Exception ex) // { // logger.LogError(ex, $"{nameof(CalendarService)}, получение конца периода. Не смог распарсить string в TimeSpan для значения {value}."); // return new TimeSpan(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, чтобы сравнять продолжительность с февралем workDays.RemoveAll(t => t.Day > 28); //Так как в базе всё храним в UTC то время с 21 часа уже соответствует следующими суткам в календаре Москвы //просто сдвигаем на день весь список if (refTime.Hour > 21) return workDays.Select(wd => wd.AddDays(-1)).ToList(); //иначе просто отдаём как есть return workDays; } /// /// Возвращает список дней между датами /// /// /// /// private 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 class Test //{ // private readonly ICalendarService calendarService; // public Test(ICalendarService calendarService) // { // this.calendarService = calendarService; // } // public async void Ttt() // { // var tService = new TestService(); // // var endPeriod = calendarService.GetEndPeriodDate(new DateOnly(2024, 1, 1), TimeSpan.Parse("30:00:00:00")); // var workDays = await calendarService.GetWorkDatesForPeriodAsync(new DateOnly(2024, 1, 1), TimeSpan.Parse("30:00:00:00"), tService.GetWeekendsAsync); // } //} //public class TestService //{ // public async Task> GetWeekendsAsync(DateOnly start, DateOnly end) // { // await Task.Delay(1000); // return new List { new DateOnly(2024, 1, 12) }; // } //} }