Skip to content

Commit

Permalink
feature: add includeZeroValues option to intervalToDuration
Browse files Browse the repository at this point in the history
  • Loading branch information
grgr-dkrk committed Apr 8, 2024
1 parent 5c1adb5 commit 35fe290
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 3 deletions.
37 changes: 34 additions & 3 deletions src/intervalToDuration/index.ts
Expand Up @@ -8,6 +8,16 @@ import { differenceInYears } from "../differenceInYears/index.js";
import { toDate } from "../toDate/index.js";
import type { Duration, Interval } from "../types.js";

type Options = { includeZeroValues?: boolean };
type RequiredDuration = Pick<
Required<Duration>,
"years" | "months" | "days" | "hours" | "minutes" | "seconds"
>;

type NormalizedDuration<O> = O extends { includeZeroValues: true }
? RequiredDuration
: Duration;

/**
* @name intervalToDuration
* @category Common Helpers
Expand All @@ -19,6 +29,7 @@ import type { Duration, Interval } from "../types.js";
* @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 interval - The interval to convert to duration
* @param options - The object with options
*
* @returns The duration object
*
Expand All @@ -28,15 +39,35 @@ import type { Duration, Interval } from "../types.js";
* start: new Date(1929, 0, 15, 12, 0, 0),
* end: new Date(1968, 3, 4, 19, 5, 0)
* })
* // => { years: 39, months: 2, days: 20, hours: 7, minutes: 5 }
*
* @example
* // Get the duration with 0 values.
* intervalToDuration({
* start: new Date(1929, 0, 15, 12, 0, 0),
* end: new Date(1968, 3, 4, 19, 5, 0)
* }, { includeZeroValues: true })
* // => { years: 39, months: 2, days: 20, hours: 7, minutes: 5, seconds: 0 }
*/
export function intervalToDuration<DateType extends Date>(
export function intervalToDuration<DateType extends Date, O extends Options>(
interval: Interval<DateType>,
): Duration {
options?: O,
): NormalizedDuration<O> {
const start = toDate(interval.start);
const end = toDate(interval.end);

const duration: Duration = {};
const duration = (
options?.includeZeroValues
? ({
years: 0,
months: 0,
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
} satisfies RequiredDuration)
: {}
) as NormalizedDuration<O>;

const years = differenceInYears(end, start);
if (years) duration.years = years;
Expand Down
66 changes: 66 additions & 0 deletions src/intervalToDuration/test.ts
Expand Up @@ -70,6 +70,72 @@ describe("intervalToDuration", () => {
expect(result).toEqual({});
});

describe("includeZeroValues", () => {
it("return zero value as properties", () => {
const start = new Date(1929, 0, 15, 12, 0, 0);
const end = new Date(1968, 3, 4, 19, 5, 0);
const result = intervalToDuration(
{ start, end },
{ includeZeroValues: true },
);

expect(result).toEqual({
years: 39,
months: 2,
days: 20,
hours: 7,
minutes: 5,
seconds: 0,
});
});

it("returns zero values when the dates are the same", () => {
const start = new Date(2020, 2, 1, 12, 0, 0);
const end = new Date(2020, 2, 1, 12, 0, 0);
const result = intervalToDuration(
{ start, end },
{ includeZeroValues: true },
);

expect(result).toEqual({
years: 0,
months: 0,
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
});
});

it("exclude zero value when 'includeZeroValues' is false", () => {
const start = new Date(1929, 0, 15, 12, 0, 0);
const end = new Date(1968, 3, 4, 19, 5, 0);
const result = intervalToDuration(
{ start, end },
{ includeZeroValues: false },
);

expect(result).toEqual({
years: 39,
months: 2,
days: 20,
hours: 7,
minutes: 5,
});
});

it("returns duration of 0 when 'includeZeroValues' is false and the dates are the same", () => {
const start = new Date(2020, 2, 1, 12, 0, 0);
const end = new Date(2020, 2, 1, 12, 0, 0);
const result = intervalToDuration(
{ start, end },
{ includeZeroValues: false },
);

expect(result).toEqual({});
});
});

describe("edge cases", () => {
it("returns correct duration for dates in the end of Feb - issue 2255", () => {
expect(intervalToDuration({
Expand Down

0 comments on commit 35fe290

Please sign in to comment.