Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
22 changes: 20 additions & 2 deletions src/modules/date/birthdate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ import { toDate } from '../../internal/date';
import { getDefaultRefDate } from '../../utils/get-default-ref-date';
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 Expand Up @@ -184,8 +202,8 @@ export function fakeDateBirthdate(
case 'age': {
// Add one day to the `from` date to avoid generating the same date as the reference date.
const oneDay = 24 * 60 * 60 * 1000;
const from = new Date(refDate).setUTCFullYear(refYear - max - 1) + oneDay;
const to = new Date(refDate).setUTCFullYear(refYear - min);
const from = sameDayInYear(refDate, refYear - max - 1) + oneDay;
const to = sameDayInYear(refDate, refYear - min);

if (from > to) {
throw new FakerError(
Expand Down
44 changes: 44 additions & 0 deletions test/modules/date.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,50 @@ describe('date', () => {
expect(age).toBeLessThanOrEqual(22);
});

it('returns a birthdate of the min age when the refDate is a leap day', () => {
const customFaker = new SimpleFaker({
randomizer: {
next() {
return 0.999999999999999;
Comment thread
ST-DDT marked this conversation as resolved.
Resolved
},
seed() {},
},
});
const refDate = new Date(Date.UTC(2024, 1, 29, 12));

const birthdate = customFaker.date.birthdate({
min: 18,
max: 18,
refDate,
mode: 'age',
});

// Born on 2006-03-01, the person turns 18 the day after the refDate.
expect(birthdate).toEqual(new Date(Date.UTC(2006, 1, 28, 12)));
Comment thread
ST-DDT marked this conversation as resolved.
Resolved
});

it('returns a birthdate of the max age when the refDate is a leap day', () => {
const customFaker = new SimpleFaker({
randomizer: {
next() {
return 0;
},
seed() {},
},
});
const refDate = new Date(Date.UTC(2024, 1, 29, 12));

const birthdate = customFaker.date.birthdate({
min: 80,
max: 80,
refDate,
mode: 'age',
});

// Born on 1943-03-01, the person is still 80 on the refDate.
expect(birthdate).toEqual(new Date(Date.UTC(1943, 2, 1, 12)));
});

it('should throw an error when the min > max year', () => {
const min = 2000;
const max = 1990;
Expand Down
Loading