using Microsoft.Extensions.Logging; using PARR.Common; using PARR.DAL.Contracts; using PARR.DAL.Services.Interfaces; namespace PARR.DAL.TransformServices { internal class NextRunModifierService : INextRunModifierService { private readonly SettingsFromDb settingsFromDb; private readonly ILogger logger; private readonly IWeekendDayService weekendDayService; public NextRunModifierService( SettingsFromDb settingsFromDb, ILogger logger, IWeekendDayService weekendDayService ) { this.settingsFromDb = settingsFromDb; this.logger = logger; this.weekendDayService = weekendDayService; } public DateTimeOffset GetNextRunByAccountRobotTimeZone(DateTimeOffset nextRun) { return nextRun.AddHours(settingsFromDb.EsppRobotAccountTimeZoneHour); } public async Task GetWorkDayAsync(DateTimeOffset nextRun) { // получаем день относительно часового пояса МСК var date = DateOnly.FromDateTime(DateResolver.IsCurrentDayRelativeMskTime(nextRun) ? nextRun.Date : nextRun.Date.AddDays(1)); if (await weekendDayService.IsWorkDayAsync(date, true)) { //текущий nextRun рабочий день, возвращаем его return nextRun; } // ищем следующий рабочий день, максимум 20 итераций, если за их кол-во не нашли рабочий, берём последний не рабочий int count = 20; while (count > 0) { date = date.AddDays(1); var isWorkDay = await weekendDayService.IsWorkDayAsync(date, true); if (isWorkDay) break; // это рабочий день, выбираем его count--; if (!isWorkDay && count == 0) logger.LogWarning($"Не нашли рабочий день за 20 итераций, взяли последний нерабочий {date}"); } // смотрим, если смещали из-за пояса МСК на день вперед, вычитаем этот день назад if (!DateResolver.IsCurrentDayRelativeMskTime(nextRun)) date = date.AddDays(-1); // считаем новый NextRun var dayCount = date.DayNumber - DateOnly.FromDateTime(nextRun.Date).DayNumber; return nextRun.AddDays(dayCount); } } }