From 948fe52807b8601907a404c7756d072e1a9bffd0 Mon Sep 17 00:00:00 2001 From: Alexey Novikov Date: Wed, 6 Mar 2024 10:44:13 -0500 Subject: [PATCH] Add getBroadcastMonth --- README.md | 4 ++++ src/calendar.ts | 3 ++- src/index.ts | 9 ++++++--- src/month.ts | 16 ++++++++++++++++ src/quarter.ts | 38 ++++++++++++++++++++++++++++++++++++++ src/week.ts | 3 +++ src/weekKey.ts | 5 ++++- src/year.ts | 19 +++++++++++++++++++ src/yearQuarter.ts | 44 ++------------------------------------------ test.js | 46 +++++++++++++++++++++++++++++++++++++++++++++- 10 files changed, 139 insertions(+), 48 deletions(-) create mode 100644 src/month.ts create mode 100644 src/quarter.ts create mode 100644 src/year.ts diff --git a/README.md b/README.md index 4232c85..1a1f902 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,10 @@ returns broadcast year for a given date returns broadcast quarter for a given date +- **getBroadcastMonth(date: DateTime): null | number** + +return broadcast month (1-12) for a given date + - **getBroadcastQuarterWeek(date: DateTime): null | [number, number]** returns `[quarter, week]` numbers for a given date diff --git a/src/calendar.ts b/src/calendar.ts index 8031e82..0bc7844 100644 --- a/src/calendar.ts +++ b/src/calendar.ts @@ -1,5 +1,4 @@ import { DateTime } from "luxon"; -import { getBroadcastYear, getBroadcastQuarter } from "./yearQuarter"; import { getBroadcastYearInterval, getBroadcastQuarterInterval, @@ -8,6 +7,8 @@ import { } from "./interval"; import { getBroadcastWeek } from "./week"; import { getBroadcastWeekKey } from "./weekKey"; +import { getBroadcastYear } from "./year"; +import { getBroadcastQuarter } from "./quarter"; export function toCalendarDateTime( broadcast: DateTime, diff --git a/src/index.ts b/src/index.ts index 2ab7b9e..88a1cf8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,12 @@ export { DateTime, Interval } from "luxon"; -export * from "./types"; +export * from "./calendar"; export * from "./format"; -export * from "./parse"; export * from "./interval"; +export * from "./month"; +export * from "./parse"; +export * from "./quarter"; +export * from "./types"; export * from "./week"; export * from "./weekKey"; +export * from "./year"; export * from "./yearQuarter"; -export * from "./calendar"; diff --git a/src/month.ts b/src/month.ts new file mode 100644 index 0000000..267d0d4 --- /dev/null +++ b/src/month.ts @@ -0,0 +1,16 @@ +import { DateTime } from "luxon"; + +import { IfValid, isValid } from "./helpers"; + +/** + return broadcast month (1-12) for a given date +**/ +export function getBroadcastMonth( + date: DateTime, +): IfValid { + if (!isValid(date)) { + return null as IfValid; + } + + return date.endOf("week").month as unknown as IfValid; +} diff --git a/src/quarter.ts b/src/quarter.ts new file mode 100644 index 0000000..30e8066 --- /dev/null +++ b/src/quarter.ts @@ -0,0 +1,38 @@ +import { DateTime } from "luxon"; + +import { IfValid, isValid } from "./helpers"; +import { getBroadcastWeek } from "./week"; + +/** + * returns broadcast quarter for a given date + **/ +export function getBroadcastQuarter( + date: DateTime, +): IfValid { + const week = getBroadcastWeek(date); + if (!isValid(date) || week === null) { + return null as IfValid; + } + + const quarterLength = 13; + return Math.min(Math.ceil(week / quarterLength), 4) as IfValid< + IsValid, + number + >; +} + +/** + * returns broadcast [quarter, week] for a given date + **/ +export function getBroadcastQuarterWeek( + date: DateTime, +): IfValid { + const week = getBroadcastWeek(date); + if (!isValid(date) || week === null) { + return null as IfValid; + } + + const quarterLength = 13; + const quarter = Math.min(Math.ceil(week / quarterLength), 4); + return [quarter, week] as IfValid; +} diff --git a/src/week.ts b/src/week.ts index 570ed4f..ac60319 100644 --- a/src/week.ts +++ b/src/week.ts @@ -13,6 +13,9 @@ function isLastWeekOverflown(date: DateTime): boolean { return yearEnd.toMillis() - date.toMillis() <= yearEndWeekDay * DAY; } +/** + * returns broadcast week number (1-54) for a given date + **/ export function getBroadcastWeek( date: DateTime, ): IfValid { diff --git a/src/weekKey.ts b/src/weekKey.ts index 33198ba..f8f9cce 100644 --- a/src/weekKey.ts +++ b/src/weekKey.ts @@ -1,8 +1,11 @@ import type { DateTime } from "luxon"; -import { getBroadcastYear } from "./yearQuarter"; import { getBroadcastWeek } from "./week"; import { IfValid } from "./helpers"; +import { getBroadcastYear } from "./year"; +/** + * returns broadcast week key for a given date. Examples: `202103`, `202232` + **/ export function getBroadcastWeekKey( date: DateTime, ): IfValid { diff --git a/src/year.ts b/src/year.ts new file mode 100644 index 0000000..8de7ed1 --- /dev/null +++ b/src/year.ts @@ -0,0 +1,19 @@ +import { DateTime } from "luxon"; + +import { getBroadcastYearInterval } from "./interval"; +import { IfValid, isValid } from "./helpers"; + +/** + * returns broadcast year for a given date + **/ +export function getBroadcastYear( + date: DateTime, +): IfValid { + const yearInterval = getBroadcastYearInterval(date); + + if (!(yearInterval && isValid(yearInterval.end))) { + return null as IfValid; + } + + return yearInterval.end.get("year") as IfValid; +} diff --git a/src/yearQuarter.ts b/src/yearQuarter.ts index 79916a8..3cc0bf5 100644 --- a/src/yearQuarter.ts +++ b/src/yearQuarter.ts @@ -1,49 +1,9 @@ import { DateTime, Interval } from "luxon"; import { YearQuarter, YearQuarters } from "./types"; -import { getBroadcastYearInterval } from "./interval"; -import { getBroadcastWeek } from "./week"; import { IfValid, isValid } from "./helpers"; - -export function getBroadcastYear( - date: DateTime, -): IfValid { - const yearInterval = getBroadcastYearInterval(date); - - if (!(yearInterval && isValid(yearInterval.end))) { - return null as IfValid; - } - - return yearInterval.end.get("year") as IfValid; -} - -export function getBroadcastQuarter( - date: DateTime, -): IfValid { - const week = getBroadcastWeek(date); - if (!isValid(date) || week === null) { - return null as IfValid; - } - - const quarterLength = 13; - return Math.min(Math.ceil(week / quarterLength), 4) as IfValid< - IsValid, - number - >; -} - -export function getBroadcastQuarterWeek( - date: DateTime, -): IfValid { - const week = getBroadcastWeek(date); - if (!isValid(date) || week === null) { - return null as IfValid; - } - - const quarterLength = 13; - const quarter = Math.min(Math.ceil(week / quarterLength), 4); - return [quarter, week] as IfValid; -} +import { getBroadcastYear } from "./year"; +import { getBroadcastQuarter } from "./quarter"; export function getBroadcastYearQuarter( date: DateTime, diff --git a/test.js b/test.js index daeef0a..e38b65d 100644 --- a/test.js +++ b/test.js @@ -4,6 +4,7 @@ const { formatToISOWithoutTZ, formatToSQLWithoutTZ, getBroadcastMonthInterval, + getBroadcastMonth, getBroadcastQuarter, getBroadcastQuarterInterval, getBroadcastQuarterIntervalFromYearQuarter, @@ -58,6 +59,7 @@ const broadcastTestData = [ { broadcastYear: 2017, broadcastQuarter: 4, + broadcastMonth: 12, week: ["2017-12-25 Mon", "2017-12-31 Sun"], month: ["2017-11-27 Mon", "2017-12-31 Sun"], quarter: ["2017-09-25 Mon", "2017-12-31 Sun"], @@ -69,6 +71,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 1, + broadcastMonth: 1, week: ["2018-12-31 Mon", "2019-01-06 Sun"], month: ["2018-12-31 Mon", "2019-01-27 Sun"], quarter: ["2018-12-31 Mon", "2019-03-31 Sun"], @@ -80,6 +83,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 1, + broadcastMonth: 3, week: ["2019-03-25 Mon", "2019-03-31 Sun"], month: ["2019-02-25 Mon", "2019-03-31 Sun"], quarter: ["2018-12-31 Mon", "2019-03-31 Sun"], @@ -91,6 +95,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 2, + broadcastMonth: 4, week: ["2019-04-01 Mon", "2019-04-07 Sun"], month: ["2019-04-01 Mon", "2019-04-28 Sun"], quarter: ["2019-04-01 Mon", "2019-06-30 Sun"], @@ -102,6 +107,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 2, + broadcastMonth: 6, week: ["2019-06-24 Mon", "2019-06-30 Sun"], month: ["2019-05-27 Mon", "2019-06-30 Sun"], quarter: ["2019-04-01 Mon", "2019-06-30 Sun"], @@ -113,6 +119,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 3, + broadcastMonth: 7, week: ["2019-07-01 Mon", "2019-07-07 Sun"], month: ["2019-07-01 Mon", "2019-07-28 Sun"], quarter: ["2019-07-01 Mon", "2019-09-29 Sun"], @@ -124,6 +131,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 3, + broadcastMonth: 9, week: ["2019-09-23 Mon", "2019-09-29 Sun"], month: ["2019-08-26 Mon", "2019-09-29 Sun"], quarter: ["2019-07-01 Mon", "2019-09-29 Sun"], @@ -135,6 +143,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 4, + broadcastMonth: 10, week: ["2019-09-30 Mon", "2019-10-06 Sun"], month: ["2019-09-30 Mon", "2019-10-27 Sun"], quarter: ["2019-09-30 Mon", "2019-12-29 Sun"], @@ -146,6 +155,7 @@ const broadcastTestData = [ { broadcastYear: 2019, broadcastQuarter: 4, + broadcastMonth: 12, week: ["2019-12-23 Mon", "2019-12-29 Sun"], month: ["2019-11-25 Mon", "2019-12-29 Sun"], quarter: ["2019-09-30 Mon", "2019-12-29 Sun"], @@ -157,6 +167,7 @@ const broadcastTestData = [ { broadcastYear: 2020, broadcastQuarter: 1, + broadcastMonth: 1, week: ["2019-12-30 Mon", "2020-01-05 Sun"], month: ["2019-12-30 Mon", "2020-01-26 Sun"], quarter: ["2019-12-30 Mon", "2020-03-29 Sun"], @@ -168,6 +179,7 @@ const broadcastTestData = [ { broadcastYear: 2020, broadcastQuarter: 2, + broadcastMonth: 5, week: ["2020-04-27 Mon", "2020-05-03 Sun"], month: ["2020-04-27 Mon", "2020-05-31 Sun"], quarter: ["2020-03-30 Mon", "2020-06-28 Sun"], @@ -179,6 +191,7 @@ const broadcastTestData = [ { broadcastYear: 2022, broadcastQuarter: 1, + broadcastMonth: 1, week: ["2021-12-27 Mon", "2022-01-02 Sun"], month: ["2021-12-27 Mon", "2022-01-30 Sun"], quarter: ["2021-12-27 Mon", "2022-03-27 Sun"], @@ -187,6 +200,31 @@ const broadcastTestData = [ ], ]; +const broadcastMonthTestDates = [ + ["2024-01-01", 1], + ["2024-01-30", 2], + ["2024-01-31", 2], + ["2024-03-31", 3], + ["2024-04-01", 4], + ["2024-04-28", 4], + ["2024-04-29", 5], + ["2024-04-30", 5], + ["2024-11-25", 12], + ["2024-11-30", 12], + ["2024-12-01", 12], + ["2024-12-31", 1], +]; + +test("getBroadcastMonth", (t) => { + broadcastMonthTestDates.forEach(([weekStart, monthNumber]) => { + t.is( + getBroadcastMonth(parseDateFromISO(weekStart)), + monthNumber, + `getBroadcastMonth ${weekStart}`, + ); + }); +}); + const broadcastWeekTestDates = [ ["2016-12-31", 1], ["2017-12-31", 53], @@ -281,7 +319,7 @@ test("parseDateFromBroadcastWeekKey", (t) => { }); }); -test("broadcast calendar interval", (t) => { +test("broadcast calendar intervals", (t) => { broadcastTestData.forEach(([weekStr, expected]) => { const week = parseDateFromISO(weekStr); @@ -324,6 +362,12 @@ test("broadcast calendar interval", (t) => { `getBroadcastQuarter expects ${expected.broadcastQuarter}`, ); + t.deepEqual( + getBroadcastMonth(week), + expected.broadcastMonth, + `getBroadcastMonth expects ${expected.broadcastMonth}`, + ); + t.deepEqual( getBroadcastYearQuarter(week), {