Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sakamossan committed Feb 2, 2024
1 parent edbba33 commit f02bd6f
Show file tree
Hide file tree
Showing 2 changed files with 276 additions and 5 deletions.
9 changes: 5 additions & 4 deletions src/roundToNearestHours/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ export interface RoundToNearestHoursOptions
* @example
* // Floor (rounds down) 10 July 2014 12:34:56 to nearest hour:
* const result = roundToNearestHours(new Date(2014, 6, 10, 12, 34, 56), { roundingMethod: 'ceil' })
* //=> Thu Jul 10 2014 13:00:00
* const result = roundToNearestHours(new Date(2014, 6, 10, 1, 23, 45), { roundingMethod: 'ceil' })
* //=> Thu Jul 10 2014 02:00:00
*
* @example
* // Ceil (rounds up) 10 July 2014 12:34:56 to nearest quarter hour:
Expand All @@ -61,8 +61,8 @@ export function roundToNearestHours<DateType extends Date>(

const _date = toDate(date);
const fractionalMinutes = _date.getMinutes() / 60;
const fractionalSeconds = _date.getSeconds() / 60;
const fractionalMilliseconds = _date.getMilliseconds() / 1000 / 60;
const fractionalSeconds = _date.getSeconds() / 60 / 60;
const fractionalMilliseconds = _date.getMilliseconds() / 1000 / 60 / 60;
const hours =
_date.getHours() +
fractionalMinutes +
Expand All @@ -73,6 +73,7 @@ export function roundToNearestHours<DateType extends Date>(
const method = options?.roundingMethod ?? "round";
const roundingMethod = getRoundingMethod(method);

// nearestTo option does not care daylight savings time
const roundedHours = roundingMethod(hours / nearestTo) * nearestTo;

const result = constructFrom(date, _date);
Expand Down
272 changes: 271 additions & 1 deletion src/roundToNearestHours/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import assert from "node:assert";
import { describe, it } from "vitest";
import {
roundToNearestHours,
// type RoundToNearestHoursOptions,
type RoundToNearestHoursOptions,
} from "./index.js";

describe("roundToNearestHours", () => {
Expand All @@ -18,6 +18,276 @@ describe("roundToNearestHours", () => {
// high
assert.deepStrictEqual(roundToNearestHours(makeDate(15, 59)), makeDate(16));
});

it("rounds to the closest x hours if nearestTo is provided", () => {
const options: RoundToNearestHoursOptions = { nearestTo: 3 };

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(9, 1), options),
makeDate(9),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(10, 30), options),
makeDate(12),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(11, 59), options),
makeDate(12),
);
});

describe("roundingMethod", () => {
it("trunc, nearestTo === 1 (default)", () => {
const options: RoundToNearestHoursOptions = { roundingMethod: "trunc" };

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 10), options),
makeDate(15),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 30), options),
makeDate(15),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 59), options),
makeDate(15),
);
});

it("trunc, nearestTo === 3", () => {
const options: RoundToNearestHoursOptions = {
roundingMethod: "trunc",
nearestTo: 3,
};

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(9), options),
makeDate(9),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(10, 30), options),
makeDate(9),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(11, 59), options),
makeDate(9),
);
});

it("floor, nearestTo === 1 (default)", () => {
const options: RoundToNearestHoursOptions = { roundingMethod: "floor" };

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(15), options),
makeDate(15),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 30), options),
makeDate(15),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 59), options),
makeDate(15),
);
});

it("floor, nearestTo === 3", () => {
const options: RoundToNearestHoursOptions = {
roundingMethod: "floor",
nearestTo: 3,
};

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(15), options),
makeDate(15),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(16, 30), options),
makeDate(15),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(17, 59), options),
makeDate(15),
);
});

it("ceil, nearestTo === 1 (default)", () => {
const options: RoundToNearestHoursOptions = { roundingMethod: "ceil" };

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 1), options),
makeDate(16),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 30), options),
makeDate(16),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 59), options),
makeDate(16),
);
});

it("ceil, nearestTo === 3", () => {
const options: RoundToNearestHoursOptions = {
roundingMethod: "ceil",
nearestTo: 3,
};

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 1), options),
makeDate(18),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(16, 30), options),
makeDate(18),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(17, 59), options),
makeDate(18),
);
});

it("round, nearestTo === 1 (default)", () => {
const options: RoundToNearestHoursOptions = { roundingMethod: "round" };

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(15), options),
makeDate(15),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 30), options),
makeDate(16),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 59), options),
makeDate(16),
);
});

it("round, nearestTo === 3", () => {
const options: RoundToNearestHoursOptions = {
roundingMethod: "round",
nearestTo: 3,
};

// low
assert.deepStrictEqual(
roundToNearestHours(makeDate(15), options),
makeDate(15),
);

// mid-point
assert.deepStrictEqual(
roundToNearestHours(makeDate(16, 30), options),
makeDate(18),
);

// high
assert.deepStrictEqual(
roundToNearestHours(makeDate(17, 59), options),
makeDate(18),
);
});
});

describe("edge cases", () => {
it("rounds up to the next day", () => {
assert.deepStrictEqual(
roundToNearestHours(new Date(2014, 6, 10, 23, 59, 59, 999)),
new Date(2014, 6, 11),
);
});

it("ceils correctly with 0 seconds and 1 millisecond", () => {
// "ceil" does not round up when exactly oclock
assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 0, 0, 0), { roundingMethod: "ceil" }),
makeDate(15),
);

assert.deepStrictEqual(
roundToNearestHours(makeDate(15, 0, 0, 1), { roundingMethod: "ceil" }),
makeDate(16),
);
});
});

describe("examples", () => {
it("example 1", () => {
const result = roundToNearestHours(new Date(2014, 6, 10, 12, 34, 56));
assert.deepStrictEqual(result, new Date(2014, 6, 10, 13));
});

it("example 2", () => {
const result = roundToNearestHours(new Date(2014, 6, 10, 12, 34, 56), {
nearestTo: 6,
});
assert.deepStrictEqual(result, new Date(2014, 6, 10, 12));
});

it("example 3", () => {
const result = roundToNearestHours(new Date(2014, 6, 10, 12, 34, 56), {
nearestTo: 8,
});
assert.deepStrictEqual(result, new Date(2014, 6, 10, 16));
});

it("example 4", () => {
const result = roundToNearestHours(new Date(2014, 6, 10, 1, 23, 45), {
roundingMethod: "ceil",
});
assert.deepStrictEqual(result, new Date(2014, 6, 10, 2));
});

it("example 5", () => {
const result = roundToNearestHours(new Date(2014, 6, 10, 12, 34, 56), {
roundingMethod: "floor",
nearestTo: 8,
});
assert.deepStrictEqual(result, new Date(2014, 6, 10, 8));
});
});
});

function makeDate(
Expand Down

0 comments on commit f02bd6f

Please sign in to comment.