2024-07-01 16:56:59 +10:00
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
|
|
using PARR.BLL.Services.Interfaces;
|
|
|
|
|
|
using PARR.Constants;
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
|
|
|
|
|
namespace PARR.BLL.Services.Implementations
|
|
|
|
|
|
{
|
|
|
|
|
|
internal class CalendarService : ICalendarService
|
|
|
|
|
|
{
|
2024-07-01 16:56:59 +10:00
|
|
|
|
private readonly ILogger<CalendarService> logger;
|
|
|
|
|
|
|
|
|
|
|
|
public CalendarService(ILogger<CalendarService> logger)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.logger = logger;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-02 11:43:59 +10:00
|
|
|
|
|
2024-07-01 16:56:59 +10:00
|
|
|
|
private DateOnly GetEndPeriodDate(DateOnly startPeriod, DistributionPeriodTypeEnum periodType, string distributionPeriod)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (periodType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case (DistributionPeriodTypeEnum.Day):
|
2024-07-02 10:52:15 +10:00
|
|
|
|
return startPeriod.AddDays(ParseInt(distributionPeriod)).AddDays(-1);
|
2024-07-01 16:56:59 +10:00
|
|
|
|
|
|
|
|
|
|
case (DistributionPeriodTypeEnum.Month):
|
2024-07-02 10:52:15 +10:00
|
|
|
|
return startPeriod.AddMonths(ParseInt(distributionPeriod)).AddDays(-1);
|
2024-07-01 16:56:59 +10:00
|
|
|
|
|
|
|
|
|
|
case (DistributionPeriodTypeEnum.Year):
|
2024-07-02 10:52:15 +10:00
|
|
|
|
return startPeriod.AddYears(ParseInt(distributionPeriod)).AddDays(-1);
|
2024-07-01 16:56:59 +10:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return startPeriod;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private int ParseInt(string value)
|
2024-06-28 16:42:53 +10:00
|
|
|
|
{
|
2024-07-01 16:56:59 +10:00
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
return int.Parse(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
logger.LogError(ex, $"{nameof(CalendarService)}, получение конца периода. Не смог распарсить string в int для значения {value}.");
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
}
|
2024-06-28 16:42:53 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-07-01 16:56:59 +10:00
|
|
|
|
//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);
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-08-20 14:10:13 +10:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Возвращает список рабочих дней с начала периода без выходных
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="startPeriod"></param>
|
|
|
|
|
|
/// <param name="refTime"></param>
|
|
|
|
|
|
/// <param name="periodType"></param>
|
|
|
|
|
|
/// <param name="distributionPeriod"></param>
|
|
|
|
|
|
/// <param name="getWeekends"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public List<DateOnly> GetWorkDatesForPeriod(DateOnly startPeriod, TimeOnly refTime, DistributionPeriodTypeEnum periodType, string distributionPeriod, GetWeekendsDelegate getWeekends)
|
2024-06-28 16:42:53 +10:00
|
|
|
|
{
|
2024-07-01 16:56:59 +10:00
|
|
|
|
var endPeriod = GetEndPeriodDate(startPeriod, periodType, distributionPeriod);
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
//не получилось сделать асинхронным
|
2024-07-01 12:09:01 +10:00
|
|
|
|
var weekends = getWeekends.Invoke(startPeriod, endPeriod).ToList(); //.ToListAsync();
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-08-20 14:10:13 +10:00
|
|
|
|
//Берем список дат за период
|
2024-07-01 12:09:01 +10:00
|
|
|
|
var workDays = GetDatesForPeriod(startPeriod, endPeriod);
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-08-20 14:10:13 +10:00
|
|
|
|
//Убираем праздники
|
2024-07-02 10:52:15 +10:00
|
|
|
|
if (weekends.Any())
|
|
|
|
|
|
workDays = workDays.Where(t => weekends.Any(x => x != t)).ToList();
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-08-20 14:10:13 +10:00
|
|
|
|
//Убираем числа старше 28, чтобы сравнять продолжительность с февралем
|
|
|
|
|
|
workDays.RemoveAll(t => t.Day > 28);
|
|
|
|
|
|
|
|
|
|
|
|
//Так как в базе всё храним в UTC то время с 21 часа уже соответствует следующими суткам в календаре Москвы
|
|
|
|
|
|
//просто сдвигаем на день весь список
|
|
|
|
|
|
if (refTime.Hour > 21)
|
|
|
|
|
|
return workDays.Select(wd => wd.AddDays(-1)).ToList();
|
|
|
|
|
|
|
|
|
|
|
|
//иначе просто отдаём как есть
|
2024-07-01 11:32:19 +10:00
|
|
|
|
return workDays;
|
2024-06-28 16:42:53 +10:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
/// <summary>
|
2024-08-20 14:10:13 +10:00
|
|
|
|
/// Возвращает список дней между датами
|
2024-07-01 11:32:19 +10:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="startPeriod"></param>
|
|
|
|
|
|
/// <param name="EndPeriod"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-07-01 12:09:01 +10:00
|
|
|
|
private List<DateOnly> GetDatesForPeriod(DateOnly startPeriod, DateOnly EndPeriod)
|
2024-06-28 16:42:53 +10:00
|
|
|
|
{
|
2024-07-01 11:32:19 +10:00
|
|
|
|
var workDaysList = new List<DateOnly>();
|
|
|
|
|
|
|
|
|
|
|
|
var currentDay = startPeriod;
|
2024-08-20 14:10:13 +10:00
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
while (currentDay <= EndPeriod)
|
|
|
|
|
|
{
|
2024-08-20 14:10:13 +10:00
|
|
|
|
workDaysList.Add(currentDay);
|
2024-07-01 11:32:19 +10:00
|
|
|
|
currentDay = currentDay.AddDays(1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return workDaysList.OrderBy(t => t).ToList();
|
2024-06-28 16:42:53 +10:00
|
|
|
|
}
|
2024-07-01 11:32:19 +10:00
|
|
|
|
}
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
|
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
//public class Test
|
|
|
|
|
|
//{
|
|
|
|
|
|
// private readonly ICalendarService calendarService;
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
// public Test(ICalendarService calendarService)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// this.calendarService = calendarService;
|
|
|
|
|
|
// }
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
|
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
// public async void Ttt()
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var tService = new TestService();
|
|
|
|
|
|
// // var endPeriod = calendarService.GetEndPeriodDate(new DateOnly(2024, 1, 1), TimeSpan.Parse("30:00:00:00"));
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
// var workDays = await calendarService.GetWorkDatesForPeriodAsync(new DateOnly(2024, 1, 1), TimeSpan.Parse("30:00:00:00"), tService.GetWeekendsAsync);
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
|
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
// }
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
|
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
//}
|
2024-06-28 16:42:53 +10:00
|
|
|
|
|
2024-07-01 11:32:19 +10:00
|
|
|
|
|
|
|
|
|
|
//public class TestService
|
|
|
|
|
|
//{
|
|
|
|
|
|
// public async Task<List<DateOnly>> GetWeekendsAsync(DateOnly start, DateOnly end)
|
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
|
|
|
|
// await Task.Delay(1000);
|
|
|
|
|
|
|
|
|
|
|
|
// return new List<DateOnly> { new DateOnly(2024, 1, 12) };
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
2024-06-28 16:42:53 +10:00
|
|
|
|
}
|