Skip to content

refactor: date accept number input #670

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
merged 9 commits into from
Mar 25, 2022
47 changes: 20 additions & 27 deletions src/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,18 @@ import type { Faker } from '.';
import type { DateEntryDefinition } from './definitions';

/**
* Converts date passed as a string or Date to a Date object. If nothing passed, takes current date.
* Converts date passed as a string, number or Date to a Date object.
* If nothing or a non parseable value is passed, takes current date.
*
* @param date Date
*/
function toDate(date?: string | Date): Date {
if (date != null) {
return new Date(date instanceof Date ? date : Date.parse(date));
function toDate(date?: string | Date | number): Date {
date = new Date(date);
if (isNaN(date.valueOf())) {
date = new Date();
}

return new Date();
}

/**
* Converts date passed as a string or Date to milliseconds. If nothing passed, takes current date.
*
* @param date Date
*/
function toMilliseconds(date?: string | Date): number {
if (date != null) {
return date instanceof Date ? date.getTime() : Date.parse(date);
}

return new Date().getTime();
return date;
}

/**
Expand Down Expand Up @@ -54,7 +43,7 @@ export class _Date {
* faker.date.past(10) // '2017-10-25T21:34:19.488Z'
* faker.date.past(10, '2020-01-01T00:00:00.000Z') // '2017-08-18T02:59:12.350Z'
*/
past(years?: number, refDate?: string | Date): Date {
past(years?: number, refDate?: string | Date | number): Date {
const date = toDate(refDate);
const range = {
min: 1000,
Expand All @@ -81,7 +70,7 @@ export class _Date {
* faker.date.future(10) // '2030-11-23T09:38:28.710Z'
* faker.date.future(10, '2020-01-01T00:00:00.000Z') // '2020-12-13T22:45:10.252Z'
*/
future(years?: number, refDate?: string | Date): Date {
future(years?: number, refDate?: string | Date | number): Date {
const date = toDate(refDate);
const range = {
min: 1000,
Expand All @@ -104,9 +93,9 @@ export class _Date {
* @example
* faker.date.between('2020-01-01T00:00:00.000Z', '2030-01-01T00:00:00.000Z') // '2026-05-16T02:22:53.002Z'
*/
between(from: string | Date, to: string | Date): Date {
const fromMs = toMilliseconds(from);
const toMs = toMilliseconds(to);
between(from: string | Date | number, to: string | Date | number): Date {
const fromMs = toDate(from).getTime();
const toMs = toDate(to).getTime();
const dateOffset = this.faker.datatype.number(toMs - fromMs);

return new Date(fromMs + dateOffset);
Expand All @@ -129,14 +118,18 @@ export class _Date {
* faker.date.betweens('2020-01-01T00:00:00.000Z', '2030-01-01T00:00:00.000Z', 2)
* // [ 2023-05-02T16:00:00.000Z, 2026-09-01T08:00:00.000Z ]
*/
betweens(from: string | Date, to: string | Date, num?: number): Date[] {
betweens(
from: string | Date | number,
to: string | Date | number,
num?: number
): Date[] {
if (typeof num === 'undefined') {
num = 3;
}

const dates: Date[] = [];

for (let i = 0; i < num; i++) {
while (dates.length < num) {
dates.push(this.between(from, to));
}

Expand All @@ -156,7 +149,7 @@ export class _Date {
* faker.date.recent(10) // '2022-01-29T06:12:12.829Z'
* faker.date.recent(10, '2020-01-01T00:00:00.000Z') // '2019-12-27T18:11:19.117Z'
*/
recent(days?: number, refDate?: string | Date): Date {
recent(days?: number, refDate?: string | Date | number): Date {
const date = toDate(refDate);
const range = {
min: 1000,
Expand All @@ -183,7 +176,7 @@ export class _Date {
* faker.date.soon(10) // '2022-02-11T05:14:39.138Z'
* faker.date.soon(10, '2020-01-01T00:00:00.000Z') // '2020-01-01T02:40:44.990Z'
*/
soon(days?: number, refDate?: string | Date): Date {
soon(days?: number, refDate?: string | Date | number): Date {
const date = toDate(refDate);
const range = {
min: 1000,
Expand Down
213 changes: 96 additions & 117 deletions test/date.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ const seededRuns = [
},
];

const converterMap = [
(d: Date) => d,
(d: Date) => d.toISOString(),
(d: Date) => d.valueOf(),
];

const NON_SEEDED_BASED_RUN = 5;

describe('date', () => {
Expand Down Expand Up @@ -384,20 +390,18 @@ describe('date', () => {
expect(date).lessThan(refDate);
});

it('should return a past date relative to given refDate', () => {
const refDate = new Date();
refDate.setFullYear(refDate.getFullYear() + 5);

let date = faker.date.past(5, refDate);

expect(date).lessThan(refDate);
expect(date).greaterThan(new Date());
it.each(converterMap)(
'should return a past date relative to given refDate',
(converter) => {
const refDate = new Date();
refDate.setFullYear(refDate.getFullYear() + 5);

date = faker.date.past(5, refDate.toISOString());
const date = faker.date.past(5, converter(refDate));

expect(date).lessThan(refDate);
expect(date).greaterThan(new Date());
});
expect(date).lessThan(refDate);
expect(date).greaterThan(new Date());
}
);
});

describe('future()', () => {
Expand All @@ -414,59 +418,50 @@ describe('date', () => {
expect(date).greaterThan(refDate); // date should be after the date given
});

it('should return a date 75 years after the date given', () => {
const refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly)
it.each(converterMap)(
'should return a date 75 years after the date given',
(converter) => {
const refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly)

let date = faker.date.future(75, refDate);
const date = faker.date.future(75, converter(refDate));

// date should be after the date given, but before the current time
expect(date).greaterThan(refDate);
expect(date).lessThan(new Date());

date = faker.date.future(75, refDate.toISOString());

// date should be after the date given, but before the current time
expect(date).greaterThan(refDate);
expect(date).lessThan(new Date());
});
// date should be after the date given, but before the current time
expect(date).greaterThan(refDate);
expect(date).lessThan(new Date());
}
);
});

describe('between()', () => {
it('should return a random date between the dates given', () => {
const from = new Date(1990, 5, 7, 9, 11, 0, 0);
const to = new Date(2000, 6, 8, 10, 12, 0, 0);

let date = faker.date.between(from, to);

expect(date).greaterThan(from);
expect(date).lessThan(to);

date = faker.date.between(from.toISOString(), to.toISOString());

expect(date).greaterThan(from);
expect(date).lessThan(to);
});
it.each(converterMap)(
'should return a random date between the dates given',
(converter) => {
const from = new Date(1990, 5, 7, 9, 11, 0, 0);
const to = new Date(2000, 6, 8, 10, 12, 0, 0);

const date = faker.date.between(converter(from), converter(to));

expect(date).greaterThan(from);
expect(date).lessThan(to);
}
);
});

describe('betweens()', () => {
it('should return an array of 3 dates ( by default ) of sorted randoms dates between the dates given', () => {
const from = new Date(1990, 5, 7, 9, 11, 0, 0);
const to = new Date(2000, 6, 8, 10, 12, 0, 0);

let dates = faker.date.betweens(from, to);

expect(dates[0]).greaterThan(from);
expect(dates[0]).lessThan(to);
expect(dates[1]).greaterThan(dates[0]);
expect(dates[2]).greaterThan(dates[1]);

dates = faker.date.betweens(from.toISOString(), to.toISOString());

expect(dates[0]).greaterThan(from);
expect(dates[0]).lessThan(to);
expect(dates[1]).greaterThan(dates[0]);
expect(dates[2]).greaterThan(dates[1]);
});
it.each(converterMap)(
'should return an array of 3 dates ( by default ) of sorted randoms dates between the dates given',
(converter) => {
const from = new Date(1990, 5, 7, 9, 11, 0, 0);
const to = new Date(2000, 6, 8, 10, 12, 0, 0);

const dates = faker.date.betweens(converter(from), converter(to));

expect(dates[0]).greaterThan(from);
expect(dates[0]).lessThan(to);
expect(dates[1]).greaterThan(dates[0]);
expect(dates[2]).greaterThan(dates[1]);
}
);
});

describe('recent()', () => {
Expand All @@ -476,36 +471,28 @@ describe('date', () => {
expect(date).lessThanOrEqual(new Date());
});

it('should return a date N days from the recent past, starting from refDate', () => {
const days = 30;
const refDate = new Date(2120, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly)

const lowerBound = new Date(
refDate.getTime() - days * 24 * 60 * 60 * 1000
);

let date = faker.date.recent(days, refDate);

expect(
lowerBound,
'`recent()` date should not be further back than `n` days ago'
).lessThanOrEqual(date);
expect(
date,
'`recent()` date should not be ahead of the starting date reference'
).lessThanOrEqual(refDate);

date = faker.date.recent(days, refDate.toISOString());

expect(
lowerBound,
'`recent()` date should not be further back than `n` days ago'
).lessThanOrEqual(date);
expect(
date,
'`recent()` date should not be ahead of the starting date reference'
).lessThanOrEqual(refDate);
});
it.each(converterMap)(
'should return a date N days from the recent past, starting from refDate',
(converter) => {
const days = 30;
const refDate = new Date(2120, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly)

const lowerBound = new Date(
refDate.getTime() - days * 24 * 60 * 60 * 1000
);

const date = faker.date.recent(days, converter(refDate));

expect(
lowerBound,
'`recent()` date should not be further back than `n` days ago'
).lessThanOrEqual(date);
expect(
date,
'`recent()` date should not be ahead of the starting date reference'
).lessThanOrEqual(refDate);
}
);
});

describe('soon()', () => {
Expand All @@ -515,36 +502,28 @@ describe('date', () => {
expect(date).greaterThanOrEqual(new Date());
});

it('should return a date N days from the recent future, starting from refDate', () => {
const days = 30;
const refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly)

const upperBound = new Date(
refDate.getTime() + days * 24 * 60 * 60 * 1000
);

let date = faker.date.soon(days, refDate);

expect(
date,
'`soon()` date should not be further ahead than `n` days ago'
).lessThanOrEqual(upperBound);
expect(
refDate,
'`soon()` date should not be behind the starting date reference'
).lessThanOrEqual(date);

date = faker.date.soon(days, refDate.toISOString());

expect(
date,
'`soon()` date should not be further ahead than `n` days ago'
).lessThanOrEqual(upperBound);
expect(
refDate,
'`soon()` date should not be behind the starting date reference'
).lessThanOrEqual(date);
});
it.each(converterMap)(
'should return a date N days from the recent future, starting from refDate',
(converter) => {
const days = 30;
const refDate = new Date(1880, 11, 9, 10, 0, 0, 0); // set the date beyond the usual calculation (to make sure this is working correctly)

const upperBound = new Date(
refDate.getTime() + days * 24 * 60 * 60 * 1000
);

const date = faker.date.soon(days, converter(refDate));

expect(
date,
'`soon()` date should not be further ahead than `n` days ago'
).lessThanOrEqual(upperBound);
expect(
refDate,
'`soon()` date should not be behind the starting date reference'
).lessThanOrEqual(date);
}
);
});

describe('month()', () => {
Expand Down