From b876aaff72f6f6c0e395b36558171809e5c8d76f Mon Sep 17 00:00:00 2001 From: Luke Tomlinson Date: Fri, 9 Sep 2022 13:50:11 -0400 Subject: [PATCH 1/5] Fix updatedAt and markedStaleOn date comparison --- dist/index.js | 26 +++++- src/classes/date-comparison.spec.ts | 35 +++++++ src/classes/date-comparison.ts | 10 ++ src/classes/issues-processor.ts | 8 +- src/classes/update-date.spec.ts | 139 ++++++++++++++++++++++++++++ 5 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 src/classes/date-comparison.spec.ts create mode 100644 src/classes/date-comparison.ts create mode 100644 src/classes/update-date.spec.ts diff --git a/dist/index.js b/dist/index.js index 18754b23a..e756b8a91 100644 --- a/dist/index.js +++ b/dist/index.js @@ -141,6 +141,24 @@ class Assignees { exports.Assignees = Assignees; +/***/ }), + +/***/ 2781: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.areDatesEqual = void 0; +function areDatesEqual(date, otherDate, toleranceInSeconds) { + const timestamp = date.getTime(); + const otherTimestamp = otherDate.getTime(); + const deltaInSeconds = Math.abs(timestamp - otherTimestamp) / 1000; + return deltaInSeconds <= toleranceInSeconds; +} +exports.areDatesEqual = areDatesEqual; + + /***/ }), /***/ 854: @@ -366,6 +384,7 @@ const milestones_1 = __nccwpck_require__(4601); const stale_operations_1 = __nccwpck_require__(5080); const statistics_1 = __nccwpck_require__(3334); const logger_service_1 = __nccwpck_require__(1973); +const date_comparison_1 = __nccwpck_require__(2781); /*** * Handle processing of issues for staleness/closure. */ @@ -737,7 +756,12 @@ class IssuesProcessor { if (issue.markedStaleThisRun) { issueLogger.info(`marked stale this run, so don't check for updates`); } - const issueHasUpdateSinceStale = new Date(issue.updated_at) > new Date(markedStaleOn); + // The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2) + // areDatesEqual makes sure they are not the same date within a certain tolerance (15 seconds in this case) + const updatedAtDate = new Date(issue.updated_at); + const markedStaleOnDate = new Date(markedStaleOn); + const issueHasUpdateSinceStale = !date_comparison_1.areDatesEqual(updatedAtDate, markedStaleOnDate, 15) && + updatedAtDate > markedStaleOnDate; issueLogger.info(`$$type has been updated since it was marked stale: ${logger_service_1.LoggerService.cyan(issueHasUpdateSinceStale)}`); // Should we un-stale this issue? if (shouldRemoveStaleWhenUpdated && diff --git a/src/classes/date-comparison.spec.ts b/src/classes/date-comparison.spec.ts new file mode 100644 index 000000000..fa7efa50b --- /dev/null +++ b/src/classes/date-comparison.spec.ts @@ -0,0 +1,35 @@ +import {areDatesEqual} from './date-comparison'; + +describe('date-comparison', (): void => { + describe('consumeOperation()', (): void => { + it('should correctly compare a before date outside tolerance', (): void => { + const date = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T14:00:00'); + expect(areDatesEqual(date, otherDate, 60)).toBe(false); + }); + + it('should correctly compare a before date inside tolerance', (): void => { + const date = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T13:00:42'); + expect(areDatesEqual(date, otherDate, 60)).toBe(true); + }); + + it('should correctly compare an after date outside tolerance', (): void => { + const date = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T12:00:00'); + expect(areDatesEqual(date, otherDate, 60)).toBe(false); + }); + + it('should correctly compare an after date inside tolerance', (): void => { + const date = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T12:59:42'); + expect(areDatesEqual(date, otherDate, 60)).toBe(true); + }); + + it('should correctly compare an exactly equal date', (): void => { + const date = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T13:00:00'); + expect(areDatesEqual(date, otherDate, 60)).toBe(true); + }); + }); +}); diff --git a/src/classes/date-comparison.ts b/src/classes/date-comparison.ts new file mode 100644 index 000000000..144db767e --- /dev/null +++ b/src/classes/date-comparison.ts @@ -0,0 +1,10 @@ +export function areDatesEqual( + date: Date, + otherDate: Date, + toleranceInSeconds: number +): boolean { + const timestamp = date.getTime(); + const otherTimestamp = otherDate.getTime(); + const deltaInSeconds = Math.abs(timestamp - otherTimestamp) / 1000; + return deltaInSeconds <= toleranceInSeconds; +} diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index d0397ebcc..0a1cbd379 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -25,6 +25,7 @@ import {StaleOperations} from './stale-operations'; import {Statistics} from './statistics'; import {LoggerService} from '../services/logger.service'; import {OctokitIssue} from '../interfaces/issue'; +import {areDatesEqual} from './date-comparison'; /*** * Handle processing of issues for staleness/closure. @@ -665,8 +666,13 @@ export class IssuesProcessor { issueLogger.info(`marked stale this run, so don't check for updates`); } + // The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2) + // areDatesEqual makes sure they are not the same date within a certain tolerance (15 seconds in this case) + const updatedAtDate = new Date(issue.updated_at); + const markedStaleOnDate = new Date(markedStaleOn); const issueHasUpdateSinceStale = - new Date(issue.updated_at) > new Date(markedStaleOn); + !areDatesEqual(updatedAtDate, markedStaleOnDate, 15) && + updatedAtDate > markedStaleOnDate; issueLogger.info( `$$type has been updated since it was marked stale: ${LoggerService.cyan( diff --git a/src/classes/update-date.spec.ts b/src/classes/update-date.spec.ts new file mode 100644 index 000000000..f2ebd2b62 --- /dev/null +++ b/src/classes/update-date.spec.ts @@ -0,0 +1,139 @@ +import {Issue} from '../src/classes/issue'; +import {IIssue} from '../src/interfaces/issue'; +import {IIssuesProcessorOptions} from '../src/interfaces/issues-processor-options'; +import {IPullRequest} from '../src/interfaces/pull-request'; +import {IssuesProcessorMock} from './classes/issues-processor-mock'; +import {DefaultProcessorOptions} from './constants/default-processor-options'; +import {generateIssue} from './functions/generate-issue'; + +let issuesProcessorBuilder: IssuesProcessorBuilder; +let issuesProcessor: IssuesProcessorMock; + +describe('handle update date', (): void => { + beforeEach((): void => { + issuesProcessorBuilder = new IssuesProcessorBuilder(); + }); + + describe('when the option "exempt-draft-pr" is disabled', (): void => { + beforeEach((): void => { + issuesProcessorBuilder.processDraftPr(); + }); + + test('should stale the pull request', async (): Promise => { + expect.assertions(1); + issuesProcessor = issuesProcessorBuilder + .toStalePrs([ + { + number: 10 + } + ]) + .build(); + + await issuesProcessor.processIssues(); + + expect(issuesProcessor.staleIssues).toHaveLength(1); + }); + }); + + describe('when the option "exempt-draft-pr" is enabled', (): void => { + beforeEach((): void => { + issuesProcessorBuilder.exemptDraftPr(); + }); + + test('should not stale the pull request', async (): Promise => { + expect.assertions(1); + issuesProcessor = issuesProcessorBuilder + .toStalePrs([ + { + number: 20 + } + ]) + .build(); + + await issuesProcessor.processIssues(); + + expect(issuesProcessor.staleIssues).toHaveLength(0); + }); + }); +}); + +class IssuesProcessorBuilder { + private _options: IIssuesProcessorOptions = { + ...DefaultProcessorOptions + }; + private _issues: Issue[] = []; + + processDraftPr(): IssuesProcessorBuilder { + this._options.exemptDraftPr = false; + + return this; + } + + exemptDraftPr(): IssuesProcessorBuilder { + this._options.exemptDraftPr = true; + + return this; + } + + issuesOrPrs(issues: Partial[]): IssuesProcessorBuilder { + this._issues = issues.map( + (issue: Readonly>, index: Readonly): Issue => + generateIssue( + this._options, + issue.number ?? index, + issue.title ?? 'dummy-title', + issue.updated_at ?? new Date().toDateString(), + issue.created_at ?? new Date().toDateString(), + !!issue.pull_request, + issue.labels ? issue.labels.map(label => label.name || '') : [] + ) + ); + + return this; + } + + prs(issues: Partial[]): IssuesProcessorBuilder { + this.issuesOrPrs( + issues.map((issue: Readonly>): Partial => { + return { + ...issue, + pull_request: {key: 'value'} + }; + }) + ); + + return this; + } + + toStalePrs(issues: Partial[]): IssuesProcessorBuilder { + this.prs( + issues.map((issue: Readonly>): Partial => { + return { + ...issue, + updated_at: '2020-01-01T17:00:00Z', + created_at: '2020-01-01T17:00:00Z' + }; + }) + ); + + return this; + } + + build(): IssuesProcessorMock { + return new IssuesProcessorMock( + this._options, + async p => (p === 1 ? this._issues : []), + async () => [], + async () => new Date().toDateString(), + async (): Promise => { + return Promise.resolve({ + number: 0, + draft: true, + head: { + ref: 'ref' + } + }); + } + ); + } +} From 6e2467dc4b64994fc13667230580a39733a4d749 Mon Sep 17 00:00:00 2001 From: Luke Tomlinson Date: Fri, 9 Sep 2022 13:55:04 -0400 Subject: [PATCH 2/5] Delete accidental file --- src/classes/update-date.spec.ts | 139 -------------------------------- 1 file changed, 139 deletions(-) delete mode 100644 src/classes/update-date.spec.ts diff --git a/src/classes/update-date.spec.ts b/src/classes/update-date.spec.ts deleted file mode 100644 index f2ebd2b62..000000000 --- a/src/classes/update-date.spec.ts +++ /dev/null @@ -1,139 +0,0 @@ -import {Issue} from '../src/classes/issue'; -import {IIssue} from '../src/interfaces/issue'; -import {IIssuesProcessorOptions} from '../src/interfaces/issues-processor-options'; -import {IPullRequest} from '../src/interfaces/pull-request'; -import {IssuesProcessorMock} from './classes/issues-processor-mock'; -import {DefaultProcessorOptions} from './constants/default-processor-options'; -import {generateIssue} from './functions/generate-issue'; - -let issuesProcessorBuilder: IssuesProcessorBuilder; -let issuesProcessor: IssuesProcessorMock; - -describe('handle update date', (): void => { - beforeEach((): void => { - issuesProcessorBuilder = new IssuesProcessorBuilder(); - }); - - describe('when the option "exempt-draft-pr" is disabled', (): void => { - beforeEach((): void => { - issuesProcessorBuilder.processDraftPr(); - }); - - test('should stale the pull request', async (): Promise => { - expect.assertions(1); - issuesProcessor = issuesProcessorBuilder - .toStalePrs([ - { - number: 10 - } - ]) - .build(); - - await issuesProcessor.processIssues(); - - expect(issuesProcessor.staleIssues).toHaveLength(1); - }); - }); - - describe('when the option "exempt-draft-pr" is enabled', (): void => { - beforeEach((): void => { - issuesProcessorBuilder.exemptDraftPr(); - }); - - test('should not stale the pull request', async (): Promise => { - expect.assertions(1); - issuesProcessor = issuesProcessorBuilder - .toStalePrs([ - { - number: 20 - } - ]) - .build(); - - await issuesProcessor.processIssues(); - - expect(issuesProcessor.staleIssues).toHaveLength(0); - }); - }); -}); - -class IssuesProcessorBuilder { - private _options: IIssuesProcessorOptions = { - ...DefaultProcessorOptions - }; - private _issues: Issue[] = []; - - processDraftPr(): IssuesProcessorBuilder { - this._options.exemptDraftPr = false; - - return this; - } - - exemptDraftPr(): IssuesProcessorBuilder { - this._options.exemptDraftPr = true; - - return this; - } - - issuesOrPrs(issues: Partial[]): IssuesProcessorBuilder { - this._issues = issues.map( - (issue: Readonly>, index: Readonly): Issue => - generateIssue( - this._options, - issue.number ?? index, - issue.title ?? 'dummy-title', - issue.updated_at ?? new Date().toDateString(), - issue.created_at ?? new Date().toDateString(), - !!issue.pull_request, - issue.labels ? issue.labels.map(label => label.name || '') : [] - ) - ); - - return this; - } - - prs(issues: Partial[]): IssuesProcessorBuilder { - this.issuesOrPrs( - issues.map((issue: Readonly>): Partial => { - return { - ...issue, - pull_request: {key: 'value'} - }; - }) - ); - - return this; - } - - toStalePrs(issues: Partial[]): IssuesProcessorBuilder { - this.prs( - issues.map((issue: Readonly>): Partial => { - return { - ...issue, - updated_at: '2020-01-01T17:00:00Z', - created_at: '2020-01-01T17:00:00Z' - }; - }) - ); - - return this; - } - - build(): IssuesProcessorMock { - return new IssuesProcessorMock( - this._options, - async p => (p === 1 ? this._issues : []), - async () => [], - async () => new Date().toDateString(), - async (): Promise => { - return Promise.resolve({ - number: 0, - draft: true, - head: { - ref: 'ref' - } - }); - } - ); - } -} From 5ef830708c0b22bde64c3de82ea8a72dc33bddee Mon Sep 17 00:00:00 2001 From: Luke Tomlinson Date: Fri, 9 Sep 2022 14:12:57 -0400 Subject: [PATCH 3/5] Refactor --- dist/index.js | 41 +++++------- src/classes/date-comparison.spec.ts | 35 ---------- src/classes/date-comparison.ts | 10 --- src/classes/issues-processor.ts | 11 ++-- src/functions/dates/date-comparison.spec.ts | 3 + src/functions/dates/date-comparison.ts | 1 + .../dates/is-date-more-recent-than.spec.ts | 66 ++++++++++++++++++- .../dates/is-date-more-recent-than.ts | 27 +++++++- 8 files changed, 118 insertions(+), 76 deletions(-) delete mode 100644 src/classes/date-comparison.spec.ts delete mode 100644 src/classes/date-comparison.ts create mode 100644 src/functions/dates/date-comparison.spec.ts create mode 100644 src/functions/dates/date-comparison.ts diff --git a/dist/index.js b/dist/index.js index e756b8a91..e401c2c09 100644 --- a/dist/index.js +++ b/dist/index.js @@ -141,24 +141,6 @@ class Assignees { exports.Assignees = Assignees; -/***/ }), - -/***/ 2781: -/***/ ((__unused_webpack_module, exports) => { - -"use strict"; - -Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.areDatesEqual = void 0; -function areDatesEqual(date, otherDate, toleranceInSeconds) { - const timestamp = date.getTime(); - const otherTimestamp = otherDate.getTime(); - const deltaInSeconds = Math.abs(timestamp - otherTimestamp) / 1000; - return deltaInSeconds <= toleranceInSeconds; -} -exports.areDatesEqual = areDatesEqual; - - /***/ }), /***/ 854: @@ -384,7 +366,6 @@ const milestones_1 = __nccwpck_require__(4601); const stale_operations_1 = __nccwpck_require__(5080); const statistics_1 = __nccwpck_require__(3334); const logger_service_1 = __nccwpck_require__(1973); -const date_comparison_1 = __nccwpck_require__(2781); /*** * Handle processing of issues for staleness/closure. */ @@ -757,11 +738,10 @@ class IssuesProcessor { issueLogger.info(`marked stale this run, so don't check for updates`); } // The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2) - // areDatesEqual makes sure they are not the same date within a certain tolerance (15 seconds in this case) + // isDateMoreRecentThan makes sure they are not the same date within a certain tolerance (15 seconds in this case) const updatedAtDate = new Date(issue.updated_at); const markedStaleOnDate = new Date(markedStaleOn); - const issueHasUpdateSinceStale = !date_comparison_1.areDatesEqual(updatedAtDate, markedStaleOnDate, 15) && - updatedAtDate > markedStaleOnDate; + const issueHasUpdateSinceStale = is_date_more_recent_than_1.isDateMoreRecentThan(updatedAtDate, markedStaleOnDate, 15); issueLogger.info(`$$type has been updated since it was marked stale: ${logger_service_1.LoggerService.cyan(issueHasUpdateSinceStale)}`); // Should we un-stale this issue? if (shouldRemoveStaleWhenUpdated && @@ -1981,12 +1961,25 @@ exports.getHumanizedDate = getHumanizedDate; "use strict"; +/// returns false if the dates are equal within the `equalityToleranceInSeconds` number of seconds +/// otherwise returns true if `comparedDate` is after `date` Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.isDateMoreRecentThan = void 0; -function isDateMoreRecentThan(date, comparedDate) { +exports.isDateEqualTo = exports.isDateMoreRecentThan = void 0; +function isDateMoreRecentThan(date, comparedDate, equalityToleranceInSeconds = 0) { + if (equalityToleranceInSeconds > 0) { + const areDatesEqual = isDateEqualTo(date, comparedDate, equalityToleranceInSeconds); + return !areDatesEqual && date > comparedDate; + } return date > comparedDate; } exports.isDateMoreRecentThan = isDateMoreRecentThan; +function isDateEqualTo(date, otherDate, toleranceInSeconds) { + const timestamp = date.getTime(); + const otherTimestamp = otherDate.getTime(); + const deltaInSeconds = Math.abs(timestamp - otherTimestamp) / 1000; + return deltaInSeconds <= toleranceInSeconds; +} +exports.isDateEqualTo = isDateEqualTo; /***/ }), diff --git a/src/classes/date-comparison.spec.ts b/src/classes/date-comparison.spec.ts deleted file mode 100644 index fa7efa50b..000000000 --- a/src/classes/date-comparison.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -import {areDatesEqual} from './date-comparison'; - -describe('date-comparison', (): void => { - describe('consumeOperation()', (): void => { - it('should correctly compare a before date outside tolerance', (): void => { - const date = new Date('2022-09-09T13:00:00'); - const otherDate = new Date('2022-09-09T14:00:00'); - expect(areDatesEqual(date, otherDate, 60)).toBe(false); - }); - - it('should correctly compare a before date inside tolerance', (): void => { - const date = new Date('2022-09-09T13:00:00'); - const otherDate = new Date('2022-09-09T13:00:42'); - expect(areDatesEqual(date, otherDate, 60)).toBe(true); - }); - - it('should correctly compare an after date outside tolerance', (): void => { - const date = new Date('2022-09-09T13:00:00'); - const otherDate = new Date('2022-09-09T12:00:00'); - expect(areDatesEqual(date, otherDate, 60)).toBe(false); - }); - - it('should correctly compare an after date inside tolerance', (): void => { - const date = new Date('2022-09-09T13:00:00'); - const otherDate = new Date('2022-09-09T12:59:42'); - expect(areDatesEqual(date, otherDate, 60)).toBe(true); - }); - - it('should correctly compare an exactly equal date', (): void => { - const date = new Date('2022-09-09T13:00:00'); - const otherDate = new Date('2022-09-09T13:00:00'); - expect(areDatesEqual(date, otherDate, 60)).toBe(true); - }); - }); -}); diff --git a/src/classes/date-comparison.ts b/src/classes/date-comparison.ts deleted file mode 100644 index 144db767e..000000000 --- a/src/classes/date-comparison.ts +++ /dev/null @@ -1,10 +0,0 @@ -export function areDatesEqual( - date: Date, - otherDate: Date, - toleranceInSeconds: number -): boolean { - const timestamp = date.getTime(); - const otherTimestamp = otherDate.getTime(); - const deltaInSeconds = Math.abs(timestamp - otherTimestamp) / 1000; - return deltaInSeconds <= toleranceInSeconds; -} diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index 0a1cbd379..1740a95f5 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -25,7 +25,6 @@ import {StaleOperations} from './stale-operations'; import {Statistics} from './statistics'; import {LoggerService} from '../services/logger.service'; import {OctokitIssue} from '../interfaces/issue'; -import {areDatesEqual} from './date-comparison'; /*** * Handle processing of issues for staleness/closure. @@ -667,12 +666,14 @@ export class IssuesProcessor { } // The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2) - // areDatesEqual makes sure they are not the same date within a certain tolerance (15 seconds in this case) + // isDateMoreRecentThan makes sure they are not the same date within a certain tolerance (15 seconds in this case) const updatedAtDate = new Date(issue.updated_at); const markedStaleOnDate = new Date(markedStaleOn); - const issueHasUpdateSinceStale = - !areDatesEqual(updatedAtDate, markedStaleOnDate, 15) && - updatedAtDate > markedStaleOnDate; + const issueHasUpdateSinceStale = isDateMoreRecentThan( + updatedAtDate, + markedStaleOnDate, + 15 + ); issueLogger.info( `$$type has been updated since it was marked stale: ${LoggerService.cyan( diff --git a/src/functions/dates/date-comparison.spec.ts b/src/functions/dates/date-comparison.spec.ts new file mode 100644 index 000000000..2eb690e15 --- /dev/null +++ b/src/functions/dates/date-comparison.spec.ts @@ -0,0 +1,3 @@ +import {areDatesEqual} from './is-date-more-recent-than'; + +describe('date-comparison', (): void => {}); diff --git a/src/functions/dates/date-comparison.ts b/src/functions/dates/date-comparison.ts new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/src/functions/dates/date-comparison.ts @@ -0,0 +1 @@ + diff --git a/src/functions/dates/is-date-more-recent-than.spec.ts b/src/functions/dates/is-date-more-recent-than.spec.ts index f564cf615..6ed1f3a1b 100644 --- a/src/functions/dates/is-date-more-recent-than.spec.ts +++ b/src/functions/dates/is-date-more-recent-than.spec.ts @@ -1,4 +1,4 @@ -import {isDateMoreRecentThan} from './is-date-more-recent-than'; +import {isDateEqualTo, isDateMoreRecentThan} from './is-date-more-recent-than'; describe('isDateMoreRecentThan()', (): void => { let date: Date; @@ -48,4 +48,68 @@ describe('isDateMoreRecentThan()', (): void => { expect(result).toStrictEqual(true); }); }); + + describe('date equality', (): void => { + it('should correctly compare a before date outside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T14:00:00'); + expect(isDateEqualTo(aDate, otherDate, 60)).toBe(false); + }); + + it('should correctly compare a before date inside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T13:00:42'); + expect(isDateEqualTo(aDate, otherDate, 60)).toBe(true); + }); + + it('should correctly compare an after date outside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T12:00:00'); + expect(isDateEqualTo(aDate, otherDate, 60)).toBe(false); + }); + + it('should correctly compare an after date inside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T12:59:42'); + expect(isDateEqualTo(aDate, otherDate, 60)).toBe(true); + }); + + it('should correctly compare an exactly equal date', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T13:00:00'); + expect(isDateEqualTo(aDate, otherDate, 60)).toBe(true); + }); + }); + + describe('date comparison with tolerances', (): void => { + it('should correctly compare a before date outside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T14:00:00'); + expect(isDateMoreRecentThan(aDate, otherDate)).toBe(false); + }); + + it('should correctly compare a before date inside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T13:00:42'); + expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(false); // considered equal here + }); + + it('should correctly compare an after date outside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T12:00:00'); + expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(true); + }); + + it('should correctly compare an after date inside tolerance', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T12:59:42'); + expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(false); // considered equal here + }); + + it('should correctly compare an exactly equal date', (): void => { + const aDate = new Date('2022-09-09T13:00:00'); + const otherDate = new Date('2022-09-09T13:00:00'); + expect(isDateMoreRecentThan(aDate, otherDate, 60)).toBe(false); + }); + }); }); diff --git a/src/functions/dates/is-date-more-recent-than.ts b/src/functions/dates/is-date-more-recent-than.ts index 482c9db8a..ee7dbda9a 100644 --- a/src/functions/dates/is-date-more-recent-than.ts +++ b/src/functions/dates/is-date-more-recent-than.ts @@ -1,6 +1,31 @@ +/// returns false if the dates are equal within the `equalityToleranceInSeconds` number of seconds +/// otherwise returns true if `comparedDate` is after `date` + export function isDateMoreRecentThan( date: Readonly, - comparedDate: Readonly + comparedDate: Readonly, + equalityToleranceInSeconds = 0 ): boolean { + if (equalityToleranceInSeconds > 0) { + const areDatesEqual = isDateEqualTo( + date, + comparedDate, + equalityToleranceInSeconds + ); + + return !areDatesEqual && date > comparedDate; + } + return date > comparedDate; } + +export function isDateEqualTo( + date: Date, + otherDate: Date, + toleranceInSeconds: number +): boolean { + const timestamp = date.getTime(); + const otherTimestamp = otherDate.getTime(); + const deltaInSeconds = Math.abs(timestamp - otherTimestamp) / 1000; + return deltaInSeconds <= toleranceInSeconds; +} From 4cfec8d1afb59dddcc06ff43bbdcc9d4ff29c118 Mon Sep 17 00:00:00 2001 From: Luke Tomlinson Date: Fri, 9 Sep 2022 14:14:20 -0400 Subject: [PATCH 4/5] Cleanup --- dist/index.js | 4 +--- src/classes/issues-processor.ts | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/dist/index.js b/dist/index.js index e401c2c09..59cca45ce 100644 --- a/dist/index.js +++ b/dist/index.js @@ -739,9 +739,7 @@ class IssuesProcessor { } // The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2) // isDateMoreRecentThan makes sure they are not the same date within a certain tolerance (15 seconds in this case) - const updatedAtDate = new Date(issue.updated_at); - const markedStaleOnDate = new Date(markedStaleOn); - const issueHasUpdateSinceStale = is_date_more_recent_than_1.isDateMoreRecentThan(updatedAtDate, markedStaleOnDate, 15); + const issueHasUpdateSinceStale = is_date_more_recent_than_1.isDateMoreRecentThan(new Date(issue.updated_at), new Date(markedStaleOn), 15); issueLogger.info(`$$type has been updated since it was marked stale: ${logger_service_1.LoggerService.cyan(issueHasUpdateSinceStale)}`); // Should we un-stale this issue? if (shouldRemoveStaleWhenUpdated && diff --git a/src/classes/issues-processor.ts b/src/classes/issues-processor.ts index 1740a95f5..db1accc64 100644 --- a/src/classes/issues-processor.ts +++ b/src/classes/issues-processor.ts @@ -667,11 +667,9 @@ export class IssuesProcessor { // The issue.updated_at and markedStaleOn are not always exactly in sync (they can be off by a second or 2) // isDateMoreRecentThan makes sure they are not the same date within a certain tolerance (15 seconds in this case) - const updatedAtDate = new Date(issue.updated_at); - const markedStaleOnDate = new Date(markedStaleOn); const issueHasUpdateSinceStale = isDateMoreRecentThan( - updatedAtDate, - markedStaleOnDate, + new Date(issue.updated_at), + new Date(markedStaleOn), 15 ); From 749a4c3dd67c936c66698121c5b2635d4828bb77 Mon Sep 17 00:00:00 2001 From: Luke Tomlinson Date: Fri, 9 Sep 2022 14:15:56 -0400 Subject: [PATCH 5/5] cleanup --- src/functions/dates/date-comparison.spec.ts | 3 --- src/functions/dates/date-comparison.ts | 1 - 2 files changed, 4 deletions(-) delete mode 100644 src/functions/dates/date-comparison.spec.ts delete mode 100644 src/functions/dates/date-comparison.ts diff --git a/src/functions/dates/date-comparison.spec.ts b/src/functions/dates/date-comparison.spec.ts deleted file mode 100644 index 2eb690e15..000000000 --- a/src/functions/dates/date-comparison.spec.ts +++ /dev/null @@ -1,3 +0,0 @@ -import {areDatesEqual} from './is-date-more-recent-than'; - -describe('date-comparison', (): void => {}); diff --git a/src/functions/dates/date-comparison.ts b/src/functions/dates/date-comparison.ts deleted file mode 100644 index 8b1378917..000000000 --- a/src/functions/dates/date-comparison.ts +++ /dev/null @@ -1 +0,0 @@ -