diff --git a/src/__tests__/setDayOfMonth.spec.ts b/src/__tests__/setDayOfMonth.spec.ts new file mode 100644 index 0000000..bb42883 --- /dev/null +++ b/src/__tests__/setDayOfMonth.spec.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from "vitest" +import { setDayOfMonth } from "../setDayOfMonth" +import { date } from "../date" + +describe("setMinutes", () => { + it("should set the minute", () => { + expect(setDayOfMonth("2024-05-06", 20)).toEqual(date("2024-05-20")) + }) + + it("shouldn't overflow to the next month", () => { + expect(setDayOfMonth("2024-06-04", 31)).toEqual(date("2024-06-30")) + }) + + it("shouldn't overflow to the next month with Feb", () => { + expect(setDayOfMonth("2023-02-20", 31)).toEqual(date("2023-02-28")) + }) + + it("shouldn't overflow to the next month with Feb leap", () => { + expect(setDayOfMonth("2024-02-20", 31)).toEqual(date("2024-02-29")) + }) + + it("should overflow when allowing overflow", () => { + expect(setDayOfMonth("2024-07-28", 35, true)).toEqual(date("2024-08-04")) + }) + + it("should underflow when given a negative number", () => { + expect(setDayOfMonth("2024-07-20 ", -3)).toEqual(date("2024-06-27")) + }) + + it("should set day to the 3th from current month", () => { + const d = date() + d.setDate(3) + expect(setDayOfMonth(null, 3)).toEqual(d) + }) +}) diff --git a/src/__tests__/setHour.spec.ts b/src/__tests__/setHour.spec.ts new file mode 100644 index 0000000..4c553a7 --- /dev/null +++ b/src/__tests__/setHour.spec.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest" +import { setHour } from "../setHour" +import { date } from "../date" + +describe("setHour", () => { + it("should set the minute", () => { + expect(setHour("2024-05-06 10:37", 17)).toEqual(date("2024-05-06 17:37")) + }) + + it("should overflow when given more than 12 hours", () => { + expect(setHour("2024-07-28 16:17", 37)).toEqual(date("2024-07-29 13:17")) + }) + + it("should underflow when given a negative number", () => { + expect(setHour("2024-03-20 13:06", -6)).toEqual(date("2024-03-19 18:06")) + }) + + it("should set hour to 6am from current time", () => { + const d = date() + d.setHours(6) + expect(setHour(null, 6)).toEqual(d) + }) +}) diff --git a/src/__tests__/setMilliseconds.spec.ts b/src/__tests__/setMilliseconds.spec.ts new file mode 100644 index 0000000..697caef --- /dev/null +++ b/src/__tests__/setMilliseconds.spec.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from "vitest" +import { setMilliseconds } from "../setMilliseconds" +import { date } from "../date" + +describe("setSeconds", () => { + it("should set the minute", () => { + expect(setMilliseconds("2024-05-06 10:00:00", 445)).toEqual( + date("2024-05-06 10:00:00.445") + ) + }) + + it("should overflow when given more than 59 seconds", () => { + expect(setMilliseconds("2024-07-28 16:10", 1584)).toEqual( + date("2024-07-28 16:10:01.584") + ) + }) + + it("should underflow when given a negative number", () => { + expect(setMilliseconds("2024-03-20 13:00", -40)).toEqual( + date("2024-03-20 12:59:59.960") + ) + }) + + it("should set ms to 54 from current time", () => { + const d = date() + d.setMilliseconds(54) + expect(setMilliseconds(null, 54)).toEqual(d) + }) +}) diff --git a/src/__tests__/setMinutes.spec.ts b/src/__tests__/setMinutes.spec.ts new file mode 100644 index 0000000..52ec36e --- /dev/null +++ b/src/__tests__/setMinutes.spec.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest" +import { setMinutes } from "../setMinutes" +import { date } from "../date" + +describe("setMinutes", () => { + it("should set the minute", () => { + expect(setMinutes("2024-05-06 10:00", 45)).toEqual(date("2024-05-06 10:45")) + }) + + it("should overflow when given more than 59 minutes", () => { + expect(setMinutes("2024-07-28 16:10", 84)).toEqual(date("2024-07-28 17:24")) + }) + + it("should underflow when given a negative number", () => { + expect(setMinutes("2024-03-20 13:00", -40)).toEqual(date("2024-03-20 12:20")) + }) + + it("should set minutes to 30 from current time", () => { + const d = date() + d.setMinutes(30) + expect(setMinutes(null, 30)).toEqual(d) + }) +}) diff --git a/src/__tests__/setMonth.spec.ts b/src/__tests__/setMonth.spec.ts new file mode 100644 index 0000000..999c32d --- /dev/null +++ b/src/__tests__/setMonth.spec.ts @@ -0,0 +1,35 @@ +import { describe, expect, it } from "vitest" +import { setMonth } from "../setMonth" +import { date } from "../date" + +describe("setMonth", () => { + it("should set month to Feb", () => { + expect(setMonth("2019-10-10", 1)).toEqual(date("2019-02-10")) + }) + + it("should prevent overflow in leap year", () => { + expect(setMonth("2024-03-31", 1)).toEqual(date("2024-02-29")) + }) + + it("should prevent overflow in none leap year", () => { + expect(setMonth("2023-03-31", 1)).toEqual(date("2023-02-28")) + }) + + it("should overflow when month has less days", () => { + expect(setMonth("2023-03-31", 3, true)).toEqual(date("2023-05-01")) + }) + + it("should overflow in months when given more than 11", () => { + expect(setMonth("2020-01-05", 13)).toEqual(date("2021-02-05")) + }) + + it("should undeflow in months when giving negative", () => { + expect(setMonth("2020-01-05", -3)).toEqual(date("2019-10-05")) + }) + + it("should set month to July with current time", () => { + const d = date() + d.setMonth(7) + expect(setMonth(null, 7)).toEqual(d) + }) +}) diff --git a/src/__tests__/setSeconds.spec.ts b/src/__tests__/setSeconds.spec.ts new file mode 100644 index 0000000..263ab02 --- /dev/null +++ b/src/__tests__/setSeconds.spec.ts @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest" +import { setSeconds } from "../setSeconds" +import { date } from "../date" + +describe("setSeconds", () => { + it("should set the minute", () => { + expect(setSeconds("2024-05-06 10:00:00", 45)).toEqual(date("2024-05-06 10:00:45")) + }) + + it("should overflow when given more than 59 seconds", () => { + expect(setSeconds("2024-07-28 16:10", 84)).toEqual(date("2024-07-28 16:11:24")) + }) + + it("should underflow when given a negative number", () => { + expect(setSeconds("2024-03-20 13:00", -40)).toEqual(date("2024-03-20 12:59:20")) + }) + + it("should set seconds to 54 from current time", () => { + const d = date() + d.setSeconds(54) + expect(setSeconds(null, 54)).toEqual(d) + }) +}) diff --git a/src/__tests__/setYear.spec.ts b/src/__tests__/setYear.spec.ts new file mode 100644 index 0000000..d0001af --- /dev/null +++ b/src/__tests__/setYear.spec.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from "vitest" +import { setYear } from "../setYear" +import { date } from "../date" + +describe("setYear", () => { + it("should set year to 1998", () => { + expect(setYear("2010-06-29", 1998)).toEqual(date("1998-06-29")) + }) + + it("should set year to 2017 with current time", () => { + const d = date() + d.setFullYear(2017) + expect(setYear(null, 2017)).toEqual(d) + }) + + it("should handle overflow from leap year to not leap year", () => { + expect(setYear("2024-02-29", 2023)).toEqual(date("2023-02-28")) + }) +}) diff --git a/src/addMonth.ts b/src/addMonth.ts index 1d6d389..385b359 100644 --- a/src/addMonth.ts +++ b/src/addMonth.ts @@ -1,6 +1,5 @@ -import { date } from "./date" -import { monthDays } from "./monthDays" -import type { DateInput, MaybeDateInput } from "./types" +import { handleOverflow } from "./handleDateOverflow" +import type { MaybeDateInput } from "./types" /** * Returns a new date object 1/n months after the original one. Keep in mind if you @@ -11,17 +10,5 @@ import type { DateInput, MaybeDateInput } from "./types" * @param [dateOverflow] - Whether or not to allow the date to overflow to another month if the inputDate’s month is out of range of the new month. */ export function addMonth(inputDate?: MaybeDateInput, count = 1, dateOverflow = false) { - const d = date(inputDate) - const dayOfMonth = d.getDate() - // If overflowing is disallowed, set the date back to the first of the month - if (!dateOverflow) d.setDate(1) - d.setMonth(d.getMonth() + count) - - // If overflowing is disallowed, we need to set the date back to the proper - // day or the last day of the month. - if (!dateOverflow) { - const daysInMonth = monthDays(d) - d.setDate(daysInMonth < dayOfMonth ? daysInMonth : dayOfMonth) - } - return d + return handleOverflow(inputDate, (d) => d.setMonth(d.getMonth() + count), dateOverflow) } diff --git a/src/addYear.ts b/src/addYear.ts index 93a04c4..eaeee57 100644 --- a/src/addYear.ts +++ b/src/addYear.ts @@ -1,5 +1,4 @@ -import { date } from "./date" -import { monthDays } from "./monthDays" +import { handleOverflow } from "./handleDateOverflow" import type { MaybeDateInput } from "./types" /** @@ -11,18 +10,9 @@ import type { MaybeDateInput } from "./types" * @param [dateOverflow] - Whether or not to allow the date to overflow to another month if the inputDate’s month is out of range of the new month. */ export function addYear(inputDate?: MaybeDateInput, count = 1, dateOverflow = false) { - const d = date(inputDate) - const dayOfMonth = d.getDate() - // If overflowing is disallowed, set the date back to the first of the month - if (!dateOverflow) d.setDate(1) - - d.setFullYear(d.getFullYear() + count) - - // If overflowing is disallowed, we need to set the date back to the proper - // day or the last day of the month. - if (!dateOverflow) { - const daysInMonth = monthDays(d) - d.setDate(daysInMonth < dayOfMonth ? daysInMonth : dayOfMonth) - } - return d + return handleOverflow( + inputDate, + (d) => d.setFullYear(d.getFullYear() + count), + dateOverflow + ) } diff --git a/src/handleDateOverflow.ts b/src/handleDateOverflow.ts new file mode 100644 index 0000000..e3d4c64 --- /dev/null +++ b/src/handleDateOverflow.ts @@ -0,0 +1,30 @@ +import { date } from "./date" +import { monthDays } from "./monthDays" +import { MaybeDateInput } from "./types" + +/** + * handles date overflow when changing month or year + * @param [inputDate] - A string, Date object or null for the current time + * @param action - the action that changes the month/year + * @param [dateOverflow] - Whether or not to allow the date to overflow to another month if the inputDate’s month is out of range of the new month. + * @returns a new Date object with the change year/month without overflowing (except if wanted to overflow) + */ +export function handleOverflow( + inputDate: MaybeDateInput | undefined, + action: (d: Date) => void, + dateOverflow = false +) { + let d = date(inputDate) + const dayOfMonth = d.getDate() + // If overflowing is disallowed, set the date back to the first of the month + if (!dateOverflow) d.setDate(1) + + action(d) + // If overflowing is disallowed, we need to set the date back to the proper + // day or the last day of the month. + if (!dateOverflow) { + const daysInMonth = monthDays(d) + d.setDate(daysInMonth < dayOfMonth ? daysInMonth : dayOfMonth) + } + return d +} diff --git a/src/index.ts b/src/index.ts index 3854023..7dec127 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,6 +14,7 @@ export { dayStart } from "./dayStart" export { format } from "./format" export { formatStr } from "./formatStr" export { fourDigitYear } from "./fourDigitYear" +export { handleOverflow } from "./handleDateOverflow" export { hourEnd } from "./hourEnd" export { hourStart } from "./hourStart" export { iso8601 } from "./iso8601" @@ -34,6 +35,13 @@ export { sameSecond } from "./sameSecond" export { sameMinute } from "./sameMinute" export { sameHour } from "./sameHour" export { sameYear } from "./sameYear" +export { setMilliseconds } from "./setMilliseconds" +export { setSeconds } from "./setSeconds" +export { setMinutes } from "./setMinutes" +export { setHour } from "./setHour" +export { setDayOfMonth } from "./setDayOfMonth" +export { setMonth } from "./setMonth" +export { setYear } from "./setYear" export { weekEnd } from "./weekEnd" export { weekStart } from "./weekStart" export { yearDays } from "./yearDays" diff --git a/src/setDayOfMonth.ts b/src/setDayOfMonth.ts new file mode 100644 index 0000000..06a02e3 --- /dev/null +++ b/src/setDayOfMonth.ts @@ -0,0 +1,23 @@ +import { date } from "./date" +import { monthDays } from "./monthDays" +import { MaybeDateInput } from "./types" + +/** + * set the day of the month in a date object + * @param [inputDate] - a date or null for current time + * @param day - the day of the month you want the date set to (1-28/29/30/31) (can over/underflow) + * @param [dateOverflow] - Whether or not to allow the date to overflow to another month if the given day isn't in the current month + */ +export function setDayOfMonth( + inputDate: MaybeDateInput, + day: number, + dateOverflow = false +) { + const d = date(inputDate) + const daysInMonth = monthDays(d) + if (!dateOverflow) { + day = day > daysInMonth ? daysInMonth : day + } + d.setDate(day) + return d +} diff --git a/src/setHour.ts b/src/setHour.ts new file mode 100644 index 0000000..38a27f6 --- /dev/null +++ b/src/setHour.ts @@ -0,0 +1,13 @@ +import { date } from "./date" +import { MaybeDateInput } from "./types" + +/** + * set the hour of a date object + * @param [inputDate] - a date or null for current time + * @param hour - the hour you want the date set to (0 - 23) (can over/underflow) + */ +export function setHour(inputDate: MaybeDateInput, hour: number) { + const d = date(inputDate) + d.setHours(hour) + return d +} diff --git a/src/setMilliseconds.ts b/src/setMilliseconds.ts new file mode 100644 index 0000000..4db4935 --- /dev/null +++ b/src/setMilliseconds.ts @@ -0,0 +1,13 @@ +import { date } from "./date" +import { MaybeDateInput } from "./types" + +/** + * set the millisecond of a date object + * @param [inputDate] - a date or null for current time + * @param second - the milliseconds you want the date set to (0 - 999) (can over/underflow) + */ +export function setMilliseconds(inputDate: MaybeDateInput, ms: number) { + const d = date(inputDate) + d.setMilliseconds(ms) + return d +} diff --git a/src/setMinutes.ts b/src/setMinutes.ts new file mode 100644 index 0000000..d2c4855 --- /dev/null +++ b/src/setMinutes.ts @@ -0,0 +1,13 @@ +import { date } from "./date" +import { MaybeDateInput } from "./types" + +/** + * set the minute of a date object + * @param [inputDate] - a date or null for current time + * @param minute - the minute you want the date set to (0 - 59) (can over/underflow) + */ +export function setMinutes(inputDate: MaybeDateInput, minute: number) { + const d = date(inputDate) + d.setMinutes(minute) + return d +} diff --git a/src/setMonth.ts b/src/setMonth.ts new file mode 100644 index 0000000..6080258 --- /dev/null +++ b/src/setMonth.ts @@ -0,0 +1,12 @@ +import { handleOverflow } from "./handleDateOverflow" +import { MaybeDateInput } from "./types" + +/** + * set the month of a date + * @param [inputDate] - a date or null for current time + * @param month - the month you want the date set to (months are 1-12/jan-dec) (can over/underflow) + * @param [dateOverflow] - Whether or not to allow the date to overflow to another month if the inputDate’s month is out of range of the new month. + */ +export function setMonth(inputDate: MaybeDateInput, month: number, dateOverflow = false) { + return handleOverflow(inputDate, (d) => d.setMonth(month), dateOverflow) +} diff --git a/src/setSeconds.ts b/src/setSeconds.ts new file mode 100644 index 0000000..3e1e772 --- /dev/null +++ b/src/setSeconds.ts @@ -0,0 +1,13 @@ +import { date } from "./date" +import { MaybeDateInput } from "./types" + +/** + * set the second of a date object + * @param [inputDate] - a date or null for current time + * @param second - the second you want the date set to (0 - 59) (can over/underflow) + */ +export function setSeconds(inputDate: MaybeDateInput, second: number) { + const d = date(inputDate) + d.setSeconds(second) + return d +} diff --git a/src/setYear.ts b/src/setYear.ts new file mode 100644 index 0000000..45bf4e8 --- /dev/null +++ b/src/setYear.ts @@ -0,0 +1,17 @@ +import { date } from "./date" +import { MaybeDateInput } from "./types" +import { handleOverflow } from "./handleDateOverflow" + +/** + * set the year of a date object + * @param inputDate - a date or null for current time + * @param year - the full year you want the date to be set to + * @param [dateOverflow] - Whether or not to allow the date to overflow to another month if the inputDate’s month is out of range of the new month. + */ +export function setYear( + inputDate: MaybeDateInput, + year: number, + dateOverflow = false +): Date { + return handleOverflow(inputDate, (d) => d.setFullYear(year), dateOverflow) +}