From 3a44d5fa48e8b28a7b9422a18262e39af1d1cb91 Mon Sep 17 00:00:00 2001 From: ST-DDT Date: Tue, 24 Jan 2023 22:51:25 +0100 Subject: [PATCH] feat(date): introduce faker.defaultRefDate and setDefaultRefDate (#1757) Co-authored-by: Shinigami --- scripts/apidoc.ts | 2 ++ src/faker.ts | 25 ++++++++++++++++ src/modules/date/index.ts | 62 +++++++++++++++++++++------------------ src/modules/git/index.ts | 6 ++-- test/date.spec.ts | 28 ++++++++++++++++++ test/faker.spec.ts | 14 +++++++++ 6 files changed, 105 insertions(+), 32 deletions(-) diff --git a/scripts/apidoc.ts b/scripts/apidoc.ts index 3e11572e1d6..352ec978bba 100644 --- a/scripts/apidoc.ts +++ b/scripts/apidoc.ts @@ -1,4 +1,5 @@ import { resolve } from 'path'; +import { faker } from '../src'; import { writeApiPagesIndex, writeApiSearchIndex, @@ -13,6 +14,7 @@ const pathOutputJson = resolve(pathOutputDir, 'typedoc.json'); async function build(): Promise { await initMarkdownRenderer(); + faker.setDefaultRefDate(Date.UTC(2023, 0, 1)); const app = newTypeDocApp(); diff --git a/src/faker.ts b/src/faker.ts index a5a6dbc275b..7224c501d31 100644 --- a/src/faker.ts +++ b/src/faker.ts @@ -51,6 +51,7 @@ export class Faker { locales: UsedLocales; private _locale: UsableLocale; private _localeFallback: UsableLocale; + private _defaultRefDate: () => Date = () => new Date(); get locale(): UsableLocale { return this._locale; @@ -80,6 +81,30 @@ export class Faker { this._localeFallback = localeFallback; } + /** + * Gets a new reference date used to generate relative dates. + */ + get defaultRefDate(): () => Date { + return this._defaultRefDate; + } + + /** + * Sets the `refDate` source to use if no `refDate` date is passed to the date methods. + * + * @param dateOrSource The function or the static value used to generate the `refDate` date instance. + * The function must return a new valid `Date` instance for every call. + * Defaults to `() => new Date()`. + */ + setDefaultRefDate( + dateOrSource: string | Date | number | (() => Date) = () => new Date() + ): void { + if (typeof dateOrSource === 'function') { + this._defaultRefDate = dateOrSource; + } else { + this._defaultRefDate = () => new Date(dateOrSource); + } + } + readonly definitions: LocaleDefinition = this.initDefinitions(); /** @internal */ diff --git a/src/modules/date/index.ts b/src/modules/date/index.ts index b3c2d71073b..5c2c49eb4d5 100644 --- a/src/modules/date/index.ts +++ b/src/modules/date/index.ts @@ -5,14 +5,18 @@ import { deprecated } from '../../internal/deprecated'; /** * Converts date passed as a string, number or Date to a Date object. - * If nothing or a non parsable value is passed, takes current date. + * If nothing or a non parsable value is passed, then it will take the value from the given fallback. * - * @param date Date + * @param date The date to convert. + * @param fallback The fallback date to use if the passed date is not valid. */ -function toDate(date?: string | Date | number): Date { +function toDate( + date?: string | Date | number, + fallback: () => Date = () => new Date() +): Date { date = new Date(date); if (isNaN(date.valueOf())) { - date = new Date(); + date = fallback(); } return date; @@ -38,7 +42,7 @@ export class DateModule { * * @param options The optional options object. * @param options.years The range of years the date may be in the past. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.recent() * @@ -59,7 +63,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }): Date; @@ -67,7 +71,7 @@ export class DateModule { * Generates a random date in the past. * * @param years The range of years the date may be in the past. Defaults to `1`. - * @param refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.recent() * @@ -86,7 +90,7 @@ export class DateModule { * * @param options The optional options object. * @param options.years The range of years the date may be in the past. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * @param legacyRefDate Deprecated, use `options.refDate` instead. * * @see faker.date.recent() @@ -111,7 +115,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }, @@ -142,7 +146,7 @@ export class DateModule { throw new FakerError('Years must be greater than 0.'); } - const date = toDate(refDate); + const date = toDate(refDate, this.faker.defaultRefDate); const range = { min: 1000, max: years * 365 * 24 * 3600 * 1000, @@ -160,7 +164,7 @@ export class DateModule { * * @param options The optional options object. * @param options.years The range of years the date may be in the future. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.soon() * @@ -181,7 +185,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }): Date; @@ -189,7 +193,7 @@ export class DateModule { * Generates a random date in the future. * * @param years The range of years the date may be in the future. Defaults to `1`. - * @param refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.soon() * @@ -208,7 +212,7 @@ export class DateModule { * * @param options The optional options object. * @param options.years The range of years the date may be in the future. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * @param legacyRefDate Deprecated, use `options.refDate` instead. * * @see faker.date.soon() @@ -233,7 +237,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }, @@ -264,7 +268,7 @@ export class DateModule { throw new FakerError('Years must be greater than 0.'); } - const date = toDate(refDate); + const date = toDate(refDate, this.faker.defaultRefDate); const range = { min: 1000, max: years * 365 * 24 * 3600 * 1000, @@ -552,7 +556,7 @@ export class DateModule { * * @param options The optional options object. * @param options.days The range of days the date may be in the past. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.past() * @@ -573,7 +577,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }): Date; @@ -581,7 +585,7 @@ export class DateModule { * Generates a random date in the recent past. * * @param days The range of days the date may be in the past. Defaults to `1`. - * @param refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.past() * @@ -600,7 +604,7 @@ export class DateModule { * * @param options The optional options object. * @param options.days The range of days the date may be in the past. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * @param legacyRefDate Deprecated, use `options.refDate` instead. * * @see faker.date.past() @@ -625,7 +629,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }, @@ -651,7 +655,7 @@ export class DateModule { throw new FakerError('Days must be greater than 0.'); } - const date = toDate(refDate); + const date = toDate(refDate, this.faker.defaultRefDate); const range = { min: 1000, max: days * 24 * 3600 * 1000, @@ -669,7 +673,7 @@ export class DateModule { * * @param options The optional options object. * @param options.days The range of days the date may be in the future. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.future() * @@ -690,7 +694,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }): Date; @@ -698,7 +702,7 @@ export class DateModule { * Generates a random date in the near future. * * @param days The range of days the date may be in the future. Defaults to `1`. - * @param refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * * @see faker.date.future() * @@ -717,7 +721,7 @@ export class DateModule { * * @param options The optional options object. * @param options.days The range of days the date may be in the future. Defaults to `1`. - * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the newly generated date. Defaults to `faker.defaultRefDate()`. * @param legacyRefDate Deprecated, use `options.refDate` instead. * * @see faker.date.future() @@ -742,7 +746,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; }, @@ -768,7 +772,7 @@ export class DateModule { throw new FakerError('Days must be greater than 0.'); } - const date = toDate(refDate); + const date = toDate(refDate, this.faker.defaultRefDate); const range = { min: 1000, max: days * 24 * 3600 * 1000, @@ -938,7 +942,7 @@ export class DateModule { /** * The date to use as reference point for the newly generated date. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; } = {} diff --git a/src/modules/git/index.ts b/src/modules/git/index.ts index 76e786ab9b6..05d24f71e55 100644 --- a/src/modules/git/index.ts +++ b/src/modules/git/index.ts @@ -143,7 +143,7 @@ export class GitModule { * Generates a date string for a git commit using the same format as `git log`. * * @param options The optional options object. - * @param options.refDate The date to use as reference point for the commit. Defaults to `new Date()`. + * @param options.refDate The date to use as reference point for the commit. Defaults to `faker.defaultRefDate()`. * * @example * faker.git.commitDate() // 'Mon Nov 7 14:40:58 2022 +0600' @@ -156,12 +156,12 @@ export class GitModule { /** * The date to use as reference point for the commit. * - * @default new Date() + * @default faker.defaultRefDate() */ refDate?: string | Date | number; } = {} ): string { - const { refDate = new Date() } = options; + const { refDate = this.faker.defaultRefDate() } = options; const dateParts = GIT_DATE_FORMAT_BASE.format( this.faker.date.recent({ days: 1, refDate }) diff --git a/test/date.spec.ts b/test/date.spec.ts index d8e617d6529..a9eaeb732b3 100644 --- a/test/date.spec.ts +++ b/test/date.spec.ts @@ -732,4 +732,32 @@ describe('date', () => { }); } }); + + describe('refDateSource', () => { + afterEach(() => { + faker.setDefaultRefDate(); + }); + + it('should use the refDateSource when refDate is not provided (with function)', () => { + faker.setDefaultRefDate(() => new Date(Date.UTC(2020, 0, 1))); + faker.seed(20200101); + const date = faker.date.past(); + expect(date).toEqual(new Date('2019-02-25T21:52:41.824Z')); + + faker.seed(20200101); + const date2 = faker.date.past(); + expect(date2).toEqual(new Date('2019-02-25T21:52:41.824Z')); + }); + + it('should use the refDateSource when refDate is not provided (with value)', () => { + faker.setDefaultRefDate(Date.UTC(2020, 0, 1)); + faker.seed(20200101); + const date = faker.date.past(); + expect(date).toEqual(new Date('2019-02-25T21:52:41.824Z')); + + faker.seed(20200101); + const date2 = faker.date.past(); + expect(date2).toEqual(new Date('2019-02-25T21:52:41.824Z')); + }); + }); }); diff --git a/test/faker.spec.ts b/test/faker.spec.ts index d418f19bdfa..50579f60d6f 100644 --- a/test/faker.spec.ts +++ b/test/faker.spec.ts @@ -141,4 +141,18 @@ describe('faker', () => { expect(actual).toBe('Oriental'); }); }); + + describe('defaultRefDate', () => { + it('should be a defined', () => { + expect(faker.defaultRefDate).toBeDefined(); + }); + + it('should be a date in the very recent past', () => { + const start = Date.now(); + const refDate = faker.defaultRefDate().getTime(); + const end = Date.now(); + expect(refDate).toBeGreaterThanOrEqual(start); + expect(refDate).toBeLessThanOrEqual(end); + }); + }); });