refs #2645. Fixed bug schedule datetime
testing/ogGui-multibranch/pipeline/head There was a failure building this commit
Details
testing/ogGui-multibranch/pipeline/head There was a failure building this commit
Details
parent
1c91b97e31
commit
570af1ed2b
|
@ -8,7 +8,7 @@
|
|||
<mat-form-field appearance="fill" class="w-full">
|
||||
<mat-label>Repetición</mat-label>
|
||||
<mat-select formControlName="recurrenceType">
|
||||
<mat-option *ngFor="let type of recurrenceTypes" [value]="type">{{ type | titlecase }}</mat-option>
|
||||
<mat-option *ngFor="let opt of recurrenceTypes" [value]="opt.value">{{ opt.label }}</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
|
|
|
@ -14,7 +14,10 @@ export class CreateTaskScheduleComponent implements OnInit{
|
|||
form: FormGroup;
|
||||
baseUrl: string;
|
||||
apiUrl: string;
|
||||
recurrenceTypes = ['none', 'custom'];
|
||||
recurrenceTypes = [
|
||||
{ value: 'none', label: 'Sin repetición' },
|
||||
{ value: 'custom', label: 'Repetición personalizada' }
|
||||
];
|
||||
weekDays: string[] = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
|
||||
isSingleDateSelected: boolean = true;
|
||||
monthsList: string[] = [
|
||||
|
@ -108,12 +111,27 @@ export class CreateTaskScheduleComponent implements OnInit{
|
|||
}
|
||||
|
||||
formatExecutionTime(time: string | Date): string {
|
||||
const date = (time instanceof Date) ? time : new Date(time);
|
||||
if (isNaN(date.getTime())) {
|
||||
console.error('Invalid execution time:', time);
|
||||
if (typeof time === 'string') {
|
||||
const hhmmMatch = time.match(/^\d{2}:\d{2}/);
|
||||
if (hhmmMatch) {
|
||||
return hhmmMatch[0];
|
||||
}
|
||||
const parsed = new Date(time);
|
||||
if (!isNaN(parsed.getTime())) {
|
||||
const hours = String(parsed.getHours()).padStart(2, '0');
|
||||
const minutes = String(parsed.getMinutes()).padStart(2, '0');
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
return date.toISOString().substring(11, 16);
|
||||
|
||||
if (time instanceof Date && !isNaN(time.getTime())) {
|
||||
const hours = String(time.getHours()).padStart(2, '0');
|
||||
const minutes = String(time.getMinutes()).padStart(2, '0');
|
||||
return `${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
convertDateToLocalISO(date: Date): string {
|
||||
|
@ -191,7 +209,7 @@ export class CreateTaskScheduleComponent implements OnInit{
|
|||
private calculateNextExecutionAndCount(): void {
|
||||
const recurrence = this.form.get('recurrenceType')?.value;
|
||||
const time = this.form.get('executionTime')?.value;
|
||||
|
||||
|
||||
if (recurrence === 'none') {
|
||||
const execDate = this.form.get('executionDate')?.value;
|
||||
if (execDate && time) {
|
||||
|
@ -200,31 +218,102 @@ export class CreateTaskScheduleComponent implements OnInit{
|
|||
this.nextExecutionDate.setHours(parseInt(hours), parseInt(minutes), 0, 0);
|
||||
this.executionCount = 1;
|
||||
}
|
||||
} else {
|
||||
const startDate = this.form.get('recurrenceDetails.initDate')?.value;
|
||||
const endDate = this.form.get('recurrenceDetails.endDate')?.value;
|
||||
const days = Object.keys(this.selectedDays).filter(day => this.selectedDays[day]);
|
||||
const months = Object.keys(this.selectedMonths).filter(month => this.selectedMonths[month]);
|
||||
|
||||
if (startDate && endDate && days.length > 0 && months.length > 0) {
|
||||
// Calcular próxima ejecución (simplificado)
|
||||
this.nextExecutionDate = new Date(startDate);
|
||||
const [hours, minutes] = time.split(':');
|
||||
this.nextExecutionDate.setHours(parseInt(hours), parseInt(minutes), 0, 0);
|
||||
|
||||
// Calcular número aproximado de ejecuciones
|
||||
this.executionCount = this.calculateExecutionCount(startDate, endDate, days.length, months.length);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const startDateValue = this.form.get('recurrenceDetails.initDate')?.value;
|
||||
const endDateValue = this.form.get('recurrenceDetails.endDate')?.value;
|
||||
|
||||
const selectedDayNames = Object.keys(this.selectedDays).filter(day => this.selectedDays[day]);
|
||||
const selectedMonthNames = Object.keys(this.selectedMonths).filter(month => this.selectedMonths[month]);
|
||||
|
||||
if (!startDateValue || !endDateValue || selectedDayNames.length === 0 || selectedMonthNames.length === 0) {
|
||||
this.nextExecutionDate = null;
|
||||
this.executionCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const startDate = new Date(startDateValue);
|
||||
const endDate = new Date(endDateValue);
|
||||
|
||||
const selectedDayIndices = new Set<number>(selectedDayNames.map(name => this.getDayIndexFromName(name)));
|
||||
const selectedMonthIndices = new Set<number>(selectedMonthNames.map(name => this.getMonthIndexFromName(name)));
|
||||
|
||||
// Conteo exacto de ejecuciones en el rango [startDate, endDate]
|
||||
this.executionCount = this.calculateExecutionCountExact(startDate, endDate, selectedDayIndices, selectedMonthIndices);
|
||||
|
||||
// Próxima ejecución >= ahora dentro del rango y criterios
|
||||
this.nextExecutionDate = this.findNextExecutionDate(startDate, endDate, time, selectedDayIndices, selectedMonthIndices);
|
||||
}
|
||||
|
||||
private calculateExecutionCount(startDate: Date, endDate: Date, daysCount: number, monthsCount: number): number {
|
||||
const start = new Date(startDate);
|
||||
private calculateExecutionCountExact(startDate: Date, endDate: Date, selectedDays: Set<number>, selectedMonths: Set<number>): number {
|
||||
const cursor = new Date(startDate);
|
||||
cursor.setHours(0, 0, 0, 0);
|
||||
const end = new Date(endDate);
|
||||
const daysDiff = Math.ceil((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
// Aproximación: días seleccionados por semana * semanas * meses activos
|
||||
return Math.ceil((daysCount / 7) * (daysDiff / 7) * (monthsCount / 12));
|
||||
end.setHours(23, 59, 59, 999);
|
||||
|
||||
let count = 0;
|
||||
while (cursor <= end) {
|
||||
if (selectedMonths.has(cursor.getMonth()) && selectedDays.has(cursor.getDay())) {
|
||||
count += 1;
|
||||
}
|
||||
cursor.setDate(cursor.getDate() + 1);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private findNextExecutionDate(startDate: Date, endDate: Date, time: string, selectedDays: Set<number>, selectedMonths: Set<number>): Date | null {
|
||||
const now = new Date();
|
||||
|
||||
const startCandidate = new Date(Math.max(new Date(startDate).setHours(0, 0, 0, 0), new Date(now).setHours(0, 0, 0, 0)));
|
||||
const endLimit = new Date(endDate);
|
||||
endLimit.setHours(23, 59, 59, 999);
|
||||
|
||||
const [hours, minutes] = (time || '00:00').split(':');
|
||||
|
||||
const candidate = new Date(startCandidate);
|
||||
while (candidate <= endLimit) {
|
||||
if (selectedMonths.has(candidate.getMonth()) && selectedDays.has(candidate.getDay())) {
|
||||
const candidateDateTime = new Date(candidate);
|
||||
candidateDateTime.setHours(parseInt(hours), parseInt(minutes), 0, 0);
|
||||
if (candidateDateTime >= now) {
|
||||
return candidateDateTime;
|
||||
}
|
||||
}
|
||||
candidate.setDate(candidate.getDate() + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private getDayIndexFromName(dayName: string): number {
|
||||
const mapping: { [key: string]: number } = {
|
||||
sunday: 0,
|
||||
monday: 1,
|
||||
tuesday: 2,
|
||||
wednesday: 3,
|
||||
thursday: 4,
|
||||
friday: 5,
|
||||
saturday: 6
|
||||
};
|
||||
return mapping[dayName.toLowerCase()] ?? -1;
|
||||
}
|
||||
|
||||
private getMonthIndexFromName(monthName: string): number {
|
||||
const mapping: { [key: string]: number } = {
|
||||
january: 0,
|
||||
february: 1,
|
||||
march: 2,
|
||||
april: 3,
|
||||
may: 4,
|
||||
june: 5,
|
||||
july: 6,
|
||||
august: 7,
|
||||
september: 8,
|
||||
october: 9,
|
||||
november: 10,
|
||||
december: 11
|
||||
};
|
||||
return mapping[monthName.toLowerCase()] ?? -1;
|
||||
}
|
||||
|
||||
formatDate(date: string | Date): string {
|
||||
|
|
Loading…
Reference in New Issue