Skip to content
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

refactor(date)!: stricter error handling of between #2719

Merged
merged 24 commits into from
Mar 28, 2024
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
3 changes: 3 additions & 0 deletions docs/guide/upgrading_v9/2711.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Require `from` and `to` in `faker.date.between()` and `betweens()`

Previously, in `faker.date.between()` and `faker.date.betweens()` if the `from` or `to` parameter was omitted (in Javascript) or an invalid date (in Javascript or Typescript), they would default to the current date or reference date. Now, both boundaries must now be given explictly. If you still need the old behavior, you can pass `Date.now()` or the reference date for `from` or `to`.
34 changes: 31 additions & 3 deletions src/modules/date/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,13 @@ export class SimpleDateModule extends SimpleModuleBase {
/**
* Generates a random date between the given boundaries.
*
* @param options The optional options object.
* @param options The options object.
* @param options.from The early date boundary.
matthewmayer marked this conversation as resolved.
Show resolved Hide resolved
* @param options.to The late date boundary.
*
* @throws If `from` or `to` are not provided.
* @throws If `from` is after `to`.
*
* @example
* faker.date.between({ from: '2020-01-01T00:00:00.000Z', to: '2030-01-01T00:00:00.000Z' }) // '2026-05-16T02:22:53.002Z'
*
Expand All @@ -174,22 +177,35 @@ export class SimpleDateModule extends SimpleModuleBase {
*/
to: string | Date | number;
}): Date {
// TODO @matthewmayer 2023-03-27: Consider removing in v10 as this check is only needed in JS
if (options == null || options.from == null || options.to == null) {
throw new FakerError(
matthewmayer marked this conversation as resolved.
Show resolved Hide resolved
'Must pass an options object with `from` and `to` values.'
);
}

const { from, to } = options;

const fromMs = toDate(from, 'from').getTime();
const toMs = toDate(to, 'to').getTime();
if (fromMs > toMs) {
throw new FakerError('`from` date must be before `to` date.');
}

return new Date(this.faker.number.int({ min: fromMs, max: toMs }));
}

/**
* Generates random dates between the given boundaries. The dates will be returned in an array sorted in chronological order.
*
* @param options The optional options object.
* @param options The options object.
* @param options.from The early date boundary.
* @param options.to The late date boundary.
matthewmayer marked this conversation as resolved.
Show resolved Hide resolved
* @param options.count The number of dates to generate. Defaults to `3`.
*
* @throws If `from` or `to` are not provided.
* @throws If `from` is after `to`.
*
* @example
* faker.date.betweens({ from: '2020-01-01T00:00:00.000Z', to: '2030-01-01T00:00:00.000Z' })
* // [
Expand Down Expand Up @@ -235,8 +251,14 @@ export class SimpleDateModule extends SimpleModuleBase {
max: number;
};
}): Date[] {
const { from, to, count = 3 } = options;
// TODO @matthewmayer 2023-03-27: Consider removing in v10 as this check is only needed in JS
if (options == null || options.from == null || options.to == null) {
throw new FakerError(
matthewmayer marked this conversation as resolved.
Show resolved Hide resolved
'Must pass an options object with `from` and `to` values.'
);
}

const { from, to, count = 3 } = options;
return this.faker.helpers
.multiple(() => this.between({ from, to }), { count })
.sort((a, b) => a.getTime() - b.getTime());
Expand Down Expand Up @@ -433,6 +455,12 @@ export class SimpleDateModule extends SimpleModuleBase {
*
* For more control, any of these methods can be customized with further options, or use [`between()`](https://fakerjs.dev/api/date.html#between) to generate a single date between two dates, or [`betweens()`](https://fakerjs.dev/api/date.html#betweens) for multiple dates.
*
* Dates can be specified as Javascript Date objects, strings or UNIX timestamps.
* For example to generate a date between 1st January 2000 and now, use:
* ```ts
* faker.date.between({ from: '2000-01-01', to: Date.now() });
* ```
*
* You can generate random localized month and weekday names using [`month()`](https://fakerjs.dev/api/date.html#month) and [`weekday()`](https://fakerjs.dev/api/date.html#weekday).
*
* These methods have additional concerns about reproducibility, see [Reproducible Results](https://fakerjs.dev/guide/usage.html#reproducible-results).
Expand Down
46 changes: 46 additions & 0 deletions test/modules/date.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,32 @@ describe('date', () => {
expect(date).lessThan(to);
}
);

it('should throw an error when from is after to', () => {
expect(() =>
faker.date.between({
from: '2000-01-01',
to: '1990-01-01',
})
).toThrow(new FakerError('`from` date must be before `to` date.'));
});

it('should allow date 0 (start of UNIX epoch)', () => {
const date = faker.date.between({
from: 0,
to: '1970-12-31',
});
expect(date).greaterThan(new Date(0));
});

it('should throw an error if to is invalid', () => {
expect(() =>
faker.date.between({
from: '1990-01-01',
to: 'not-a-date',
})
).toThrow(new FakerError('Invalid to date: not-a-date'));
});
});

describe('betweens()', () => {
Expand Down Expand Up @@ -325,6 +351,26 @@ describe('date', () => {
expect(dates.at(-1)).lessThan(to);
}
);

it('should throw an error when from is after to', () => {
expect(() =>
faker.date.betweens({
from: '2000-01-01',
to: '1990-01-01',
count: 3,
})
).toThrow(new FakerError('`from` date must be before `to` date.'));
});

it('should throw an error if to is invalid', () => {
expect(() =>
faker.date.betweens({
from: '1990-01-01',
to: 'not-a-date',
count: 3,
})
).toThrow(new FakerError('Invalid to date: not-a-date'));
});
});

describe('recent()', () => {
Expand Down
Loading