Compare commits
4 Commits
fb9578fec0
...
4af552b29e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4af552b29e | ||
|
|
9d3273191b | ||
|
|
246e8e69ae | ||
|
|
e9c9e9f03e |
@@ -111,7 +111,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"RabbitMq": {
|
"RabbitMq": {
|
||||||
"ThresholdConnections": 29
|
"ThresholdConnections": 33
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user