Compare commits

..

4 Commits

4 changed files with 420 additions and 140 deletions

View File

@@ -111,7 +111,7 @@
} }
], ],
"RabbitMq": { "RabbitMq": {
"ThresholdConnections": 29 "ThresholdConnections": 33
} }
} }
} }

View File

@@ -70,23 +70,12 @@ namespace PARR.Core.Services.NextRunServices.Subservices
var nextRun = referenceDate; var nextRun = referenceDate;
//var finalOffset = new TimeSpan(3, 0, 0) + (offset ?? TimeSpan.Zero);
var finalOffset = offset ?? TimeSpan.Zero; var finalOffset = offset ?? TimeSpan.Zero;
var offsetReferenceDate = referenceDate.ToOffset(finalOffset); var offsetReferenceDate = referenceDate.ToOffset(finalOffset);
logger.LogDebug("Дата после добавления offset - {offsetReferenceDate}", offsetReferenceDate); logger.LogDebug("Дата после добавления offset - {offsetReferenceDate}", offsetReferenceDate);
////---------
//// Для рассчета по МСК времени, потому что в ЮТС может быть еще ВСК, а по МСК это уже ПНД
//var offsetReferenceDate = referenceDate.ToOffset(new TimeSpan(3, 0, 0));
////---------
//// может быть offset ,это работает когда смещение для УЗ ЕСПП и применение ЗО РГ
//if (offset.HasValue)
// offsetReferenceDate = offsetReferenceDate.Off(offsetReferenceDate.Offset + offset);
// //offsetReferenceDate = offsetReferenceDate.Add(offset.Value);
switch (esppSchedule.TypeSchedule.Id) switch (esppSchedule.TypeSchedule.Id)
{ {
@@ -108,6 +97,9 @@ namespace PARR.Core.Services.NextRunServices.Subservices
case (int)EsppSchTypeScheduleEnum.Annually2: case (int)EsppSchTypeScheduleEnum.Annually2:
nextRun = GetNextDateAnnually2(esppSchedule.Values, offsetReferenceDate); nextRun = GetNextDateAnnually2(esppSchedule.Values, offsetReferenceDate);
break; break;
default:
logger.LogError("Неподдерживаемый тип расписания ЕСПП: {TypeId}", esppSchedule.TypeSchedule.Id);
throw new NotSupportedException($"Тип расписания {esppSchedule.TypeSchedule.Id} не поддерживается.");
} }
logger.LogDebug("Рассчитанная дата, с учетом offset: {nextRun}", nextRun); logger.LogDebug("Рассчитанная дата, с учетом offset: {nextRun}", nextRun);
@@ -139,6 +131,14 @@ namespace PARR.Core.Services.NextRunServices.Subservices
return esppSchedule; return esppSchedule;
} }
/// <summary>
/// Регулярно. Каждые 1 час, 2 часа, Каждые пол года...
/// </summary>
/// <param name="values"></param>
/// <param name="referenceDate"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private DateTimeOffset GetNextDateRegularly(List<EsppScheduleValDto> values, DateTimeOffset referenceDate) private DateTimeOffset GetNextDateRegularly(List<EsppScheduleValDto> values, DateTimeOffset referenceDate)
{ {
var regDict = new Dictionary<string, int> var regDict = new Dictionary<string, int>
@@ -159,27 +159,63 @@ namespace PARR.Core.Services.NextRunServices.Subservices
{"Каждые полгода", 4380}, {"Каждые полгода", 4380},
{"Каждые 1,5 года", 13140}, {"Каждые 1,5 года", 13140},
{"Каждые 3 года", 26280}, {"Каждые 3 года", 26280},
}; };
var key = values[0].Value.Value;
if (!regDict.TryGetValue(values[0].Value.Value, out int regNum)) if (!regDict.TryGetValue(key, out int regMinutes))
{ {
logger.LogError("Неизвестное значение: {Value}", values[0].Value.Value); logger.LogError("Неизвестное значение: {Value}", key);
throw new ArgumentException($"Неизвестное значение: {values[0].Value.Value}"); throw new ArgumentException($"Неизвестное значение: {key}");
} }
#region Старая логика
//var calcDay = referenceDate;
////TODO: вот это повторяется от метода к методу
////Если итоговая дата указывает на прошлое, то повторяем расчёт и уходим в рекурсию
//if (calcDay < DateTimeOffset.UtcNow /* || calcDay <= referenceDate*/)
// calcDay = GetNextDateRegularly(values, calcDay.AddHours(regMinutes));
//return calcDay;
#endregion
var nowInTargetZone = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
var calcDay = referenceDate; var calcDay = referenceDate;
//TODO: вот это повторяется от метода к методу // Если referenceDate далеко в прошлом, не шагаем по минутам в цикле.
//Если итоговая дата указывает на прошлое, то повторяем расчёт и уходим в рекурсию // Сразу вычисляем, сколько целых интервалов нужно прибавить, чтобы догнать текущее время.
if (calcDay < DateTimeOffset.UtcNow) if (calcDay < nowInTargetZone)
calcDay = GetNextDateRegularly(values, calcDay.AddHours(regNum)); {
double totalMinutesPast = (nowInTargetZone - calcDay).TotalMinutes;
return calcDay; // Считаем, сколько полных интервалов помещается в этот отрезок времени
long intervalsToSkip = (long)Math.Ceiling(totalMinutesPast / regMinutes);
calcDay = calcDay.AddMinutes(intervalsToSkip * regMinutes);
}
// Проверяем условия и делаем микро-шаги, если необходимо
while (true)
{
if (calcDay >= referenceDate && calcDay >= nowInTargetZone)
{
return calcDay;
}
calcDay = calcDay.AddMinutes(regMinutes);
}
} }
/// <summary>
/// Еженедельно, каждый понедельник, вторник, среду...
/// </summary>
/// <param name="values"></param>
/// <param name="referenceDate"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private DateTimeOffset GetNextDateWeekly(List<EsppScheduleValDto> values, DateTimeOffset referenceDate) private DateTimeOffset GetNextDateWeekly(List<EsppScheduleValDto> values, DateTimeOffset referenceDate)
{ {
if (!dwDict.TryGetValue(values[0].Value.Value, out int dwNum)) if (!dwDict.TryGetValue(values[0].Value.Value, out int dwNum))
@@ -188,71 +224,155 @@ namespace PARR.Core.Services.NextRunServices.Subservices
throw new ArgumentException($"Неизвестное значение: {values[0].Value.Value}"); throw new ArgumentException($"Неизвестное значение: {values[0].Value.Value}");
} }
#region Старая логика
//var calcDay = referenceDate;
//if (calcDay < DateTimeOffset.UtcNow)
//{
// var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
// calcDay = new DateTimeOffset(
// nowInTargetTz.Year,
// nowInTargetTz.Month,
// nowInTargetTz.Day,
// referenceDate.Hour,
// referenceDate.Minute,
// referenceDate.Second,
// referenceDate.Offset
// );
//}
//if (((int)calcDay.DayOfWeek) != dwNum)
// calcDay = OffsetToDayOfWeek(dwNum, calcDay);
////Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
//if (calcDay < DateTimeOffset.UtcNow || calcDay <= referenceDate)
// calcDay = GetNextDateWeekly(values, calcDay.AddDays(7));//а вот тут что-то новенькое
//return calcDay;
#endregion
var nowInTargetZone = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
var calcDay = referenceDate; var calcDay = referenceDate;
if (calcDay < DateTimeOffset.UtcNow)
// Сдвигаем дату вперед до нужного дня недели
if ((int)calcDay.DayOfWeek != dwNum)
{ {
var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset); calcDay = OffsetToDayOfWeek(dwNum, calcDay);
calcDay = new DateTimeOffset(
nowInTargetTz.Year,
//DateTimeOffset.UtcNow.Year,
nowInTargetTz.Month,
//DateTimeOffset.UtcNow.Month,
nowInTargetTz.Day,
//DateTimeOffset.UtcNow.Day,
referenceDate.Hour,
referenceDate.Minute,
referenceDate.Second,
referenceDate.Offset
);
} }
// Если получившаяся дата все еще глубоко в прошлом,
// не шагаем неделями в цикле, а мгновенно прыгаем ближе к текущему времени математикой.
if (calcDay < nowInTargetZone)
{
double totalDaysPast = (nowInTargetZone - calcDay).TotalDays;
if (((int)calcDay.DayOfWeek) != dwNum) // Вычисляем, сколько полных недель (по 7 дней) нужно прибавить
calcDay = OffsetToDayOfWeek(dwNum, calcDay); long weeksToSkip = (long)Math.Ceiling(totalDaysPast / 7);
//TODO: вот это повторяется от метода к методу calcDay = calcDay.AddDays(weeksToSkip * 7);
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию }
if (calcDay < DateTimeOffset.UtcNow)
calcDay = GetNextDateWeekly(values, calcDay.AddDays(7));//а вот тут что-то новенькое
return calcDay; while (true)
{
// Условие выхода: дата в будущем относительно точки старта И текущего времени
if (calcDay >= referenceDate && calcDay >= nowInTargetZone)
{
return calcDay;
}
// Если условия не выполнены, делаем шаг ровно в одну неделю (7 дней)
calcDay = calcDay.AddDays(7);
}
} }
/// <summary>
/// Ежемесячно, 1, 2, 3... числа
/// </summary>
/// <param name="values"></param>
/// <param name="referenceDate"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private DateTimeOffset GetNextDateMonthly(List<EsppScheduleValDto> values, DateTimeOffset referenceDate) private DateTimeOffset GetNextDateMonthly(List<EsppScheduleValDto> values, DateTimeOffset referenceDate)
{ {
if (!int.TryParse(values[0].Value.Value, out int dayNum)) if (!int.TryParse(values[0].Value.Value, out int targetDay))
{ {
logger.LogError("Неизвестное значение дня месяца: {Value}", values[0].Value.Value); logger.LogError("Неизвестное значение дня месяца: {Value}", values[0].Value.Value);
throw new ArgumentException($"Неизвестное значение: {values[0].Value.Value}"); throw new ArgumentException($"Неизвестное значение: {values[0].Value.Value}");
} }
var calcDay = new DateTimeOffset(referenceDate.Year, referenceDate.Month, dayNum, referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset); #region старая логика, не учтено попадание например 31 числа на февраль. Нет сравнения что расчитанная дата новее или равна refDate
if (referenceDate < DateTimeOffset.UtcNow) //var calcDay = new DateTimeOffset(referenceDate.Year, referenceDate.Month, targetDay, referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset);
//if (referenceDate < DateTimeOffset.UtcNow)
//{
// var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
// calcDay = new DateTimeOffset(
// nowInTargetTz.Year,
// nowInTargetTz.Month,
// targetDay,
// referenceDate.Hour,
// referenceDate.Minute,
// referenceDate.Second,
// referenceDate.Offset
// );
//}
////Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
//if (calcDay < DateTimeOffset.UtcNow /*|| calcDay <= referenceDate*/)
// calcDay = GetNextDateMonthly(values, calcDay.AddMonths(1));
//return calcDay;
#endregion
// Начинаем проверку с текущего месяца и года переданной referenceDate
var baseDate = referenceDate;
int monthsToAdd = 0;
var nowInTargetZone = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
while (true)
{ {
var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset); // Каждую итерацию мы отталкиваемся от исходной точки и прибавляем +1, +2, +3 месяца
calcDay = new DateTimeOffset( var nextMonthDate = baseDate.AddMonths(monthsToAdd);
nowInTargetTz.Year, int year = nextMonthDate.Year;
nowInTargetTz.Month, int month = nextMonthDate.Month;
dayNum,
referenceDate.Hour, // Если в этом конкретном месяце НЕТ нужного нам дня (например, 31 числа в апреле или 30 в феврале)
referenceDate.Minute, if (targetDay > DateTime.DaysInMonth(year, month))
referenceDate.Second, {
referenceDate.Offset // Пропускаем этот месяц и идем на следующий круг цикла
); monthsToAdd++;
//calcDay = new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, dayNum, referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset); continue;
}
// Если день существует, безопасно собираем дату
var calcDay = new DateTimeOffset(
year, month, targetDay,
referenceDate.Hour, referenceDate.Minute, referenceDate.Second,
referenceDate.Offset
);
// Условие выхода: дата строго в будущем относительно referenceDate и текущего UTC-времени
if (calcDay >= referenceDate && calcDay >= nowInTargetZone)
{
return calcDay;
}
// Если дата правильная, но она в прошлом — переходим к следующему месяцу
monthsToAdd++;
} }
//TODO: вот это повторяется от метода к методу
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
if (calcDay < DateTimeOffset.UtcNow)
calcDay = GetNextDateMonthly(values, calcDay.AddMonths(1));
return calcDay;
} }
/// <summary>
/// Ежемесячно-2, Первый понедельник, Третий вторник
/// </summary>
/// <param name="values"></param>
/// <param name="referenceDate"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="InvalidOperationException"></exception>
private DateTimeOffset GetNextDateMonthly2(List<EsppScheduleValDto> values, DateTimeOffset referenceDate) private DateTimeOffset GetNextDateMonthly2(List<EsppScheduleValDto> values, DateTimeOffset referenceDate)
{ {
if (!orderDict.TryGetValue(values[0].Value.Value, out int orderNum)) if (!orderDict.TryGetValue(values[0].Value.Value, out int orderNum))
@@ -267,56 +387,113 @@ namespace PARR.Core.Services.NextRunServices.Subservices
throw new ArgumentException($"Неизвестное значение: {values[1].Value.Value}"); throw new ArgumentException($"Неизвестное значение: {values[1].Value.Value}");
} }
#region Старая логика
//var startDay = referenceDate < DateTimeOffset.UtcNow //var startDay = referenceDate < DateTimeOffset.UtcNow
// ? new DateTimeOffset(DateTimeOffset.UtcNow.Year, DateTimeOffset.UtcNow.Month, 1, referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset) // ? new DateTimeOffset(
// : new DateTimeOffset(referenceDate.Year, referenceDate.Month, 1, referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset); // DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset).Year,
// DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset).Month,
// 1,
// referenceDate.Hour,
// referenceDate.Minute,
// referenceDate.Second,
// referenceDate.Offset
// )
// : new DateTimeOffset(
// referenceDate.Year,
// referenceDate.Month,
// 1,
// referenceDate.Hour,
// referenceDate.Minute,
// referenceDate.Second,
// referenceDate.Offset
// );
var startDay = referenceDate < DateTimeOffset.UtcNow //var daysList = FindAllDaysInMonth(dwNum, startDay);
? new DateTimeOffset(
DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset).Year,
DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset).Month,
1,
referenceDate.Hour,
referenceDate.Minute,
referenceDate.Second,
referenceDate.Offset
)
: new DateTimeOffset(
referenceDate.Year,
referenceDate.Month,
1,
referenceDate.Hour,
referenceDate.Minute,
referenceDate.Second,
referenceDate.Offset
);
var daysList = FindAllDaysInMonth(dwNum, startDay); //DateTimeOffset calcDay;
//if (orderNum == 5) // Последний
//{
// calcDay = daysList.Last();
//}
//else
//{
// if (orderNum > daysList.Count)
// {
// logger.LogError("Запрошенный порядковый день недели ({OrderNum}) не существует в месяце {Month}/{Year}. Найдено только {Count} дней.", orderNum, startDay.Month, startDay.Year, daysList.Count);
// throw new InvalidOperationException($"Запрошенный порядковый день недели ({orderNum}) не существует в месяце {startDay.Month}/{startDay.Year}. Найдено только {daysList.Count} дней.");
// }
// else
// calcDay = daysList[orderNum - 1];
//}
DateTimeOffset calcDay; //// Если дата <= текущей, переходим на следующий месяц
if (orderNum == 5) // Последний //if (calcDay <= DateTimeOffset.UtcNow /*|| calcDay <= referenceDate*/)
// return GetNextDateMonthly2(values, startDay.AddMonths(1));
//return calcDay;
#endregion
var nowInTargetZone = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
// Начинаем расчет с текущего месяца referenceDate
int monthsToAdd = 0;
while (true)
{ {
calcDay = daysList.Last(); var currentMonthDate = referenceDate.AddMonths(monthsToAdd);
}
else // Безопасно формируем первое число для проверяемого месяца
{ var startDayOfMonth = new DateTimeOffset(
if (orderNum > daysList.Count) currentMonthDate.Year,
currentMonthDate.Month,
1,
referenceDate.Hour,
referenceDate.Minute,
referenceDate.Second,
referenceDate.Offset
);
// Ищем все нужные дни недели в этом месяце
var daysList = FindAllDaysInMonth(dwNum, startDayOfMonth);
DateTimeOffset calcDay;
if (orderNum == 5) // Последний день недели в месяце (например, последняя пятница)
{ {
logger.LogError("Запрошенный порядковый день недели ({OrderNum}) не существует в месяце {Month}/{Year}. Найдено только {Count} дней.", orderNum, startDay.Month, startDay.Year, daysList.Count); calcDay = daysList.Last();
throw new InvalidOperationException($"Запрошенный порядковый день недели ({orderNum}) не существует в месяце {startDay.Month}/{startDay.Year}. Найдено только {daysList.Count} дней.");
} }
else else
{
// Умная защита: если в текущем месяце нет 5-го вторника,
// мы не выкидываем ошибку приложения, а мягко идем искать в следующем месяце
if (orderNum > daysList.Count)
{
monthsToAdd++;
continue;
}
calcDay = daysList[orderNum - 1]; calcDay = daysList[orderNum - 1];
}
// 3. Условие выхода (точно такое же, как во всех предыдущих методах)
if (calcDay >= referenceDate && calcDay >= nowInTargetZone)
{
return calcDay;
}
// Если дата правильная, но она в прошлом — переходим к следующему календарному месяцу
monthsToAdd++;
} }
// Если дата <= текущей, переходим на следующий месяц
if (calcDay <= DateTimeOffset.UtcNow)
return GetNextDateMonthly2(values, startDay.AddMonths(1));
return calcDay;
} }
/// <summary>
/// Ежегодно, Январь 17, Февраль 20
/// </summary>
/// <param name="values"></param>
/// <param name="referenceDate"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private DateTimeOffset GetNextDateAnnually(List<EsppScheduleValDto> values, DateTimeOffset referenceDate) private DateTimeOffset GetNextDateAnnually(List<EsppScheduleValDto> values, DateTimeOffset referenceDate)
{ {
@@ -332,26 +509,73 @@ namespace PARR.Core.Services.NextRunServices.Subservices
throw new ArgumentException($"Неизвестное значение: {values[0].Value.Value}"); throw new ArgumentException($"Неизвестное значение: {values[0].Value.Value}");
} }
//var year = (referenceDate.Year < DateTimeOffset.UtcNow.Year) ? DateTimeOffset.UtcNow.Year : referenceDate.Year; #region Старая логика
//сравниваем года в одном часовом поясе ////сравниваем года в одном часовом поясе
var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset); //var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
var year = (referenceDate.Year < nowInTargetTz.Year) //var year = (referenceDate.Year < nowInTargetTz.Year)
? nowInTargetTz.Year // ? nowInTargetTz.Year
: referenceDate.Year; // : referenceDate.Year;
var calcDay = new DateTimeOffset( //var calcDay = new DateTimeOffset(
year, monthNum, dayNum, // year, monthNum, dayNum,
referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset); // referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset);
//TODO: вот это повторяется от метода к методу ////Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию //if (calcDay < DateTimeOffset.UtcNow /*|| calcDay <= referenceDate*/)
if (calcDay < DateTimeOffset.UtcNow) // calcDay = GetNextDateAnnually(values, calcDay.AddYears(1));
calcDay = GetNextDateAnnually(values, calcDay.AddYears(1));
return calcDay; //return calcDay;
#endregion
var nowInTargetZone = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
// Начинаем расчет с года переданной referenceDate
int yearsToAdd = 0;
while (true)
{
// Вычисляем текущий проверяемый год относительно исходной referenceDate
var currentYearDate = referenceDate.AddYears(yearsToAdd);
int year = currentYearDate.Year;
// ЗАЩИТА: Если в этом году нет такого дня (например, 29 февраля в невисокосном году)
if (dayNum > DateTime.DaysInMonth(year, monthNum))
{
// Просто пропускаем этот год и переходим к следующему
yearsToAdd++;
continue;
}
// Если день существует, безопасно собираем дату
var calcDay = new DateTimeOffset(
year,
monthNum,
dayNum,
referenceDate.Hour,
referenceDate.Minute,
referenceDate.Second,
referenceDate.Offset
);
// Проверяем условия выхода (абсолютно одинаково для всех методов)
if (calcDay >= referenceDate && calcDay >= nowInTargetZone)
{
return calcDay;
}
// Если дата в прошлом — переходим на следующий год
yearsToAdd++;
}
} }
/// <summary>
/// Ежегодно-2, Первый понедельник января
/// </summary>
/// <param name="values"></param>
/// <param name="referenceDate"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private DateTimeOffset GetNextDateAnnually2(List<EsppScheduleValDto> values, DateTimeOffset referenceDate) private DateTimeOffset GetNextDateAnnually2(List<EsppScheduleValDto> values, DateTimeOffset referenceDate)
{ {
var monthADict = new Dictionary<string, int> var monthADict = new Dictionary<string, int>
@@ -386,34 +610,90 @@ namespace PARR.Core.Services.NextRunServices.Subservices
throw new ArgumentException($"Неизвестное значение: {values[1].Value.Value}"); throw new ArgumentException($"Неизвестное значение: {values[1].Value.Value}");
} }
//var year = (referenceDate.Year < DateTimeOffset.UtcNow.Year) ? DateTimeOffset.UtcNow.Year : referenceDate.Year;
// сравниваем года в одном часовом поясе
var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
var year = (referenceDate.Year < nowInTargetTz.Year)
? nowInTargetTz.Year
: referenceDate.Year;
//if (year == DateTimeOffset.UtcNow.Year && referenceDate.Month < DateTimeOffset.UtcNow.Month) #region Старая логика
if (year == nowInTargetTz.Year && referenceDate.Month < nowInTargetTz.Month)
year += 1;
var calcDay = new DateTimeOffset( //// сравниваем года в одном часовом поясе
year, monthNum, 1, //var nowInTargetTz = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset); //var year = (referenceDate.Year < nowInTargetTz.Year)
// ? nowInTargetTz.Year
// : referenceDate.Year;
List<DateTimeOffset> daysList = FindAllDaysInMonth(dwNum, calcDay); ////if (year == DateTimeOffset.UtcNow.Year && referenceDate.Month < DateTimeOffset.UtcNow.Month)
//if (year == nowInTargetTz.Year && referenceDate.Month < nowInTargetTz.Month)
// year += 1;
if (orderNum == 5)//5-последний //var calcDay = new DateTimeOffset(
calcDay = daysList.Last(); // year, monthNum, 1,
else // referenceDate.Hour, referenceDate.Minute, referenceDate.Second, referenceDate.Offset);
calcDay = daysList[orderNum - 1];
//TODO: вот это повторяется от метода к методу //List<DateTimeOffset> daysList = FindAllDaysInMonth(dwNum, calcDay);
//Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
if (calcDay < DateTimeOffset.UtcNow)
calcDay = GetNextDateAnnually2(values, calcDay.AddYears(1));
return calcDay; //if (orderNum == 5)//5-последний
// calcDay = daysList.Last();
//else
// calcDay = daysList[orderNum - 1];
////Если итоговая дата указывает на прошлое, то повторяем расчёт и ухоим в рекурсию
//if (calcDay < DateTimeOffset.UtcNow /*|| calcDay <= referenceDate*/)
// calcDay = GetNextDateAnnually2(values, calcDay.AddYears(1));
//return calcDay;
#endregion
var nowInTargetZone = DateTimeOffset.UtcNow.ToOffset(referenceDate.Offset);
// Начинаем расчет с года переданной referenceDate
int yearsToAdd = 0;
while (true)
{
// Сдвигаем проверяемый год относительно исходной даты
var currentYearDate = referenceDate.AddYears(yearsToAdd);
int year = currentYearDate.Year;
// Формируем первое число целевого месяца для проверяемого года
var startDayOfMonth = new DateTimeOffset(
year,
monthNum,
1,
referenceDate.Hour,
referenceDate.Minute,
referenceDate.Second,
referenceDate.Offset
);
// Ищем все нужные дни недели в этом месяце
var daysList = FindAllDaysInMonth(dwNum, startDayOfMonth);
DateTimeOffset calcDay;
if (orderNum == 5) // 5 означает "Последний день недели в месяце"
{
calcDay = daysList.Last();
}
else
{
// Умная защита: если в этом году в этом месяце НЕТ 5-го выбранного дня недели
if (orderNum > daysList.Count)
{
// Мы не падаем с ошибкой, а просто переходим к проверке следующего года
yearsToAdd++;
continue;
}
calcDay = daysList[orderNum - 1];
}
if (calcDay >= referenceDate && calcDay >= nowInTargetZone)
{
return calcDay;
}
// Если вычисленная дата в прошлом — переходим на следующий год
yearsToAdd++;
}
} }

View File

@@ -29,7 +29,7 @@
"QueueName": "parr-next-run-updater", "QueueName": "parr-next-run-updater",
"User": "next_run_updater_reader", "User": "next_run_updater_reader",
"Password": "LJFgsifgFidfsdvi123#!23", "Password": "LJFgsifgFidfsdvi123#!23",
"PrefetchCount": 100 "PrefetchCount": 1
} }
} }
} }

View File

@@ -40,7 +40,7 @@ services:
fluentd-buffer-limit: '52428800' fluentd-buffer-limit: '52428800'
tag: parr.next-run-rabbit.serilog tag: parr.next-run-rabbit.serilog
deploy: deploy:
replicas: 1 replicas: 4
networks: networks:
- parr-network - parr-network