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

feature: Update addYears function to make it timezone agnostic conversion #3783

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/addYears/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { addMonths } from "../addMonths/index.js";

/**
* @name addYears
* @category Year Helpers
Expand All @@ -8,7 +6,8 @@ import { addMonths } from "../addMonths/index.js";
* @description
* Add the specified number of years to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments.
* Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
*
* @param date - The date to be changed
* @param amount - The amount of years to be added.
Expand All @@ -24,5 +23,8 @@ export function addYears<DateType extends Date>(
date: DateType | number | string,
amount: number,
): DateType {
return addMonths(date, amount * 12);
// Convert date to UTC to perform timezone agnostic calculations
const utcDate = new Date(date);
utcDate.setUTCMonth(utcDate.getUTCMonth() + amount * 12);
return utcDate as DateType;
}
33 changes: 20 additions & 13 deletions src/addYears/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,33 @@ import { addYears } from "./index.js";

describe("addYears", () => {
it("adds the given number of years", () => {
const result = addYears(new Date(2014, 8 /* Sep */, 1), 5);
expect(result).toEqual(new Date(2019, 8 /* Sep */, 1));
const result = addYears(new Date(Date.UTC(2014, 8 /* Sep */, 1)), 5);
expect(result).toEqual(new Date(Date.UTC(2019, 8 /* Sep */, 1)));
});

it("accepts a timestamp", () => {
const result = addYears(new Date(2014, 8 /* Sep */, 1).getTime(), 12);
expect(result).toEqual(new Date(2026, 8 /* Sep */, 1));
const result = addYears(Date.UTC(2014, 8 /* Sep */, 1), 12);
expect(result).toEqual(new Date(Date.UTC(2026, 8 /* Sep */, 1)));
});

it("does not mutate the original date", () => {
const date = new Date(2014, 8 /* Sep */, 1);
const date = new Date(Date.UTC(2014, 8 /* Sep */, 1));
addYears(date, 12);
expect(date).toEqual(new Date(2014, 8 /* Sep */, 1));
expect(date).toEqual(new Date(Date.UTC(2014, 8 /* Sep */, 1)));
});

it("handles the leap years properly", () => {
const result = addYears(new Date(2016, 1 /* Feb */, 29), 1);
expect(result).toEqual(new Date(2017, 1 /* Feb */, 28));
const result = addYears(new Date(Date.UTC(2016, 1 /* Feb */, 29)), 1);
expect(result).toEqual(new Date(Date.UTC(2017, 1 /* Feb */, 28)));
});

it("handles dates before 100 AD", () => {
const initialDate = new Date(0);
initialDate.setFullYear(0, 1 /* Feb */, 29);
initialDate.setHours(0, 0, 0, 0);
initialDate.setUTCFullYear(0, 1 /* Feb */, 29);
initialDate.setUTCHours(0, 0, 0, 0);
const expectedResult = new Date(0);
expectedResult.setFullYear(1, 1 /* Feb */, 28);
expectedResult.setHours(0, 0, 0, 0);
expectedResult.setUTCFullYear(1, 1 /* Feb */, 28);
expectedResult.setUTCHours(0, 0, 0, 0);
const result = addYears(initialDate, 1);
expect(result).toEqual(expectedResult);
});
Expand All @@ -40,7 +40,14 @@ describe("addYears", () => {
});

it("returns `Invalid Date` if the given amount is NaN", () => {
const result = addYears(new Date(2014, 8 /* Sep */, 1), NaN);
const result = addYears(new Date(Date.UTC(2014, 8 /* Sep */, 1)), NaN);
expect(result instanceof Date && isNaN(result.getTime())).toBe(true);
});

it("operates on UTC dates", () => {
const date = new Date(Date.UTC(2014, 8 /* Sep */, 1));
const result = addYears(date, 5);
const expectedResult = new Date(Date.UTC(2019, 8 /* Sep */, 1));
expect(result).toEqual(expectedResult);
});
});