Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
16 changes: 16 additions & 0 deletions src/modules/date/_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Returns the timestamp of the given date moved to the given year (in UTC).
* February 29 becomes February 28 in a common year instead of rolling over to March 1.
*
* @param date The date to move.
* @param year The year to move the date to.
*/
export function sameDayInYear(date: Date, year: number): number {
const result = new Date(date);
result.setUTCFullYear(year);
if (result.getUTCMonth() !== date.getUTCMonth()) {
result.setUTCDate(0);
}

return result.getTime();
}
19 changes: 1 addition & 18 deletions src/modules/date/birthdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,9 @@ import type { FakerCore } from '../../core';
import { FakerError } from '../../errors/faker-error';
import { toDate } from '../../internal/date';
import { getDefaultRefDate } from '../../utils/get-default-ref-date';
import { sameDayInYear } from './_utils';
import { fakeDateBetween } from './between';

/**
* Returns the timestamp of the given date moved to the given year.
* February 29 becomes February 28 in a common year instead of rolling over to March 1,
* so a person born on the returned day has their birthday on or before the given date.
*
* @param date The date to move.
* @param year The year to move the date to.
*/
function sameDayInYear(date: Date, year: number): number {
const result = new Date(date);
result.setUTCFullYear(year);
if (result.getUTCMonth() !== date.getUTCMonth()) {
result.setUTCDate(0);
}

return result.getTime();
}

/**
* Returns a random birthdate. By default, the birthdate is generated for an adult between 18 and 80 years old.
* But you can customize the `'age'` range or the `'year'` range to generate a more specific birthdate.
Expand Down
10 changes: 5 additions & 5 deletions src/modules/date/future.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FakerError } from '../../errors/faker-error';
import { toDate } from '../../internal/date';
import { getDefaultRefDate } from '../../utils/get-default-ref-date';
import type { NumberOrRange } from '../../utils/types';
import { sameDayInYear } from './_utils';
import { fakeDateBetween } from './between';

/**
Expand Down Expand Up @@ -62,13 +63,12 @@ export function fakeDateFuture(
}

const time = toDate(refDate);
const from = new Date(time);
from.setUTCFullYear(from.getUTCFullYear() + years.min);
const to = new Date(time);
to.setUTCFullYear(to.getUTCFullYear() + years.max);
const year = time.getUTCFullYear();
const from = sameDayInYear(time, year + years.min);
const to = sameDayInYear(time, year + years.max);

return fakeDateBetween(fakerCore, {
from: from.getTime() + 1000,
from: from + 1000,
to,
});
}
10 changes: 5 additions & 5 deletions src/modules/date/past.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FakerError } from '../../errors/faker-error';
import { toDate } from '../../internal/date';
import { getDefaultRefDate } from '../../utils/get-default-ref-date';
import type { NumberOrRange } from '../../utils/types';
import { sameDayInYear } from './_utils';
import { fakeDateBetween } from './between';

/**
Expand Down Expand Up @@ -62,13 +63,12 @@ export function fakeDatePast(
}

const time = toDate(refDate);
const from = new Date(time);
from.setUTCFullYear(from.getUTCFullYear() - years.max);
const to = new Date(time);
to.setUTCFullYear(to.getUTCFullYear() - years.min);
const year = time.getUTCFullYear();
const from = sameDayInYear(time, year - years.max);
const to = sameDayInYear(time, year - years.min);

return fakeDateBetween(fakerCore, {
from,
to: to.getTime() - 1000,
to: to - 1000,
});
}
76 changes: 76 additions & 0 deletions test/modules/date.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,44 @@ describe('date', () => {
expect(date).toEqual(new Date(Date.UTC(1980, 2, 1)));
});

it('should return a date at least min years in the past when the refDate is a leap day', () => {
const customFaker = new SimpleFaker({
randomizer: {
next() {
return MERSENNE_MAX_VALUE;
},
seed() {},
},
});

const date = customFaker.date.past({
years: { min: 1, max: 2 },
refDate: new Date(Date.UTC(2024, 1, 29, 12)),
});

// One year before 2024-02-29 is 2023-02-28, not 2023-03-01.
Comment thread
ST-DDT marked this conversation as resolved.
Resolved
expect(date).toEqual(new Date(Date.UTC(2023, 1, 28, 11, 59, 59)));
});

it('should return a date at most max years in the past when the refDate is a leap day', () => {
const customFaker = new SimpleFaker({
randomizer: {
next() {
return 0;
},
seed() {},
},
});

const date = customFaker.date.past({
years: { min: 1, max: 2 },
refDate: new Date(Date.UTC(2024, 1, 29, 12)),
});

// Two years before 2024-02-29 is 2022-02-28, not 2022-03-01.
expect(date).toEqual(new Date(Date.UTC(2022, 1, 28, 12)));
});

it('should throw an error when years = 0', () => {
const refDate = new Date();
expect(() =>
Expand Down Expand Up @@ -368,6 +406,44 @@ describe('date', () => {
expect(date).toEqual(new Date(Date.UTC(2060, 2, 1)));
});

it('should return a date at least min years in the future when the refDate is a leap day', () => {
const customFaker = new SimpleFaker({
randomizer: {
next() {
return 0;
},
seed() {},
},
});

const date = customFaker.date.future({
years: { min: 1, max: 2 },
refDate: new Date(Date.UTC(2024, 1, 29, 12)),
});

// One year after 2024-02-29 is 2025-02-28, not 2025-03-01.
expect(date).toEqual(new Date(Date.UTC(2025, 1, 28, 12, 0, 1)));
});

it('should return a date at most max years in the future when the refDate is a leap day', () => {
const customFaker = new SimpleFaker({
randomizer: {
next() {
return MERSENNE_MAX_VALUE;
},
seed() {},
},
});

const date = customFaker.date.future({
years: { min: 1, max: 2 },
refDate: new Date(Date.UTC(2024, 1, 29, 12)),
});

// Two years after 2024-02-29 is 2026-02-28, not 2026-03-01.
Comment thread
ST-DDT marked this conversation as resolved.
Resolved
expect(date).toEqual(new Date(Date.UTC(2026, 1, 28, 12)));
});

it('should throw an error when years = 0', () => {
const refDate = new Date();
expect(() =>
Expand Down
Loading