Skip to content

refactor: create nextOccurrence and nextOccurrenceDate methods in Occurrence #2983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 41 additions & 42 deletions src/Task/Recurrence.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,45 @@ export class Occurrence {

return true;
}

/**
* Gets next occurrence (start/scheduled/due date) keeping the relative distance
* with the reference date
*
* @param nextReferenceDate
* @param currentOccurrence start/scheduled/due date
* @private
*/
public nextOccurrenceDate(currentOccurrence: Moment | null, nextReferenceDate: Date) {
if (currentOccurrence === null) {
return null;
}
const originalDifference = window.moment.duration(currentOccurrence.diff(this.referenceDate));

// Cloning so that original won't be manipulated:
const nextOccurrence = window.moment(nextReferenceDate);
// Rounding days to handle cross daylight-savings-time recurrences.
nextOccurrence.add(Math.round(originalDifference.asDays()), 'days');
return nextOccurrence;
}

public nextOccurrence(next: Date): Occurrence {
// Only if a reference date is given. A reference date will exist if at
// least one of the other dates is set.
if (this.referenceDate === null) {
return new Occurrence({
startDate: null,
scheduledDate: null,
dueDate: null,
});
}

return new Occurrence({
startDate: this.nextOccurrenceDate(this.startDate, next),
scheduledDate: this.nextOccurrenceDate(this.scheduledDate, next),
dueDate: this.nextOccurrenceDate(this.dueDate, next),
});
}
}

export class Recurrence {
Expand Down Expand Up @@ -139,54 +178,14 @@ export class Recurrence {
*
* @param today - Optional date representing the completion date. Defaults to today.
*/
public next(today = window.moment()): {
startDate: Moment | null;
scheduledDate: Moment | null;
dueDate: Moment | null;
} | null {
public next(today = window.moment()): Occurrence | null {
const next = this.nextReferenceDate(today);

if (next === null) {
return null;
}

// Only if a reference date is given. A reference date will exist if at
// least one of the other dates is set.
if (this.occurrence.referenceDate === null) {
return {
startDate: null,
scheduledDate: null,
dueDate: null,
};
}

return {
startDate: this.nextOccurrence(next, this.occurrence.startDate),
scheduledDate: this.nextOccurrence(next, this.occurrence.scheduledDate),
dueDate: this.nextOccurrence(next, this.occurrence.dueDate),
};
}

/**
* Gets next occurrence (start/scheduled/due date) keeping the relative distance
* with the reference date
*
* @param nextReferenceDate
* @param currentOccurrence start/scheduled/due date
* @private
*/
private nextOccurrence(nextReferenceDate: Date, currentOccurrence: Moment | null): Moment | null {
if (currentOccurrence === null) {
return null;
}

const originalDifference = window.moment.duration(currentOccurrence.diff(this.occurrence.referenceDate));

// Cloning so that original won't be manipulated:
const nextOccurrence = window.moment(nextReferenceDate);
// Rounding days to handle cross daylight-savings-time recurrences.
nextOccurrence.add(Math.round(originalDifference.asDays()), 'days');
return nextOccurrence;
return this.occurrence.nextOccurrence(next);
}

public identicalTo(other: Recurrence) {
Expand Down
7 changes: 2 additions & 5 deletions tests/Task/Recurrence.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@ describe('Recurrence', () => {
const next = recurrence!.next();

// Assert
expect(next).toStrictEqual({
startDate: null,
scheduledDate: null,
dueDate: null,
});
const nullOccurrence = new Occurrence({ startDate: null, scheduledDate: null, dueDate: null });
expect(next).toStrictEqual(nullOccurrence);
});

it('creates a recurrence the next month, even on the 31st', () => {
Expand Down