From a97188fbc1e28134e03dabe26974a11240305e17 Mon Sep 17 00:00:00 2001 From: hwanyoungChoi Date: Thu, 27 Nov 2025 17:19:41 +0900 Subject: [PATCH] feat: add plugin isoWeekOfMonth --- src/plugin/isoWeekOfMonth/index.js | 33 +++++++++++++++ test/plugin/isoWeekOfMonth.test.js | 64 ++++++++++++++++++++++++++++++ types/plugin/isoWeekOfMonth.d.ts | 16 ++++++++ 3 files changed, 113 insertions(+) create mode 100644 src/plugin/isoWeekOfMonth/index.js create mode 100644 test/plugin/isoWeekOfMonth.test.js create mode 100644 types/plugin/isoWeekOfMonth.d.ts diff --git a/src/plugin/isoWeekOfMonth/index.js b/src/plugin/isoWeekOfMonth/index.js new file mode 100644 index 000000000..6da8470c2 --- /dev/null +++ b/src/plugin/isoWeekOfMonth/index.js @@ -0,0 +1,33 @@ +export default (o, dayjsClass) => { + dayjsClass.prototype.isoWeekOfMonth = function () { + const day = this.day() + const daysToSubtract = day === 0 ? 6 : day - 1 + const monday = this.subtract(daysToSubtract, 'day') + + const thursday = monday.add(3, 'day') + const year = thursday.year() + const month = thursday.month() + + const firstDayOfMonth = thursday.startOf('month') + + const firstDayOfMonthDay = firstDayOfMonth.day() + const daysToFirstMonday = + firstDayOfMonthDay === 0 ? 6 : firstDayOfMonthDay - 1 + const firstMonday = firstDayOfMonth.subtract(daysToFirstMonday, 'day') + let firstThursday = firstMonday.add(3, 'day') + + if (firstThursday.month() < month || firstThursday.year() < year) { + firstThursday = firstThursday.add(1, 'week') + } + + const week = + Math.round((thursday.valueOf() - firstThursday.valueOf()) / + (7 * 24 * 60 * 60 * 1000)) + 1 + + return { + year, + month: month + 1, + week + } + } +} diff --git a/test/plugin/isoWeekOfMonth.test.js b/test/plugin/isoWeekOfMonth.test.js new file mode 100644 index 000000000..448914ee7 --- /dev/null +++ b/test/plugin/isoWeekOfMonth.test.js @@ -0,0 +1,64 @@ +import dayjs from '../../src' +import isoWeekOfMonth from '../../src/plugin/isoWeekOfMonth' + +dayjs.extend(isoWeekOfMonth) + +it('returns Jan 1st ISO week for 2024-12-31 (across year)', () => { + const result = dayjs('2024-12-31').isoWeekOfMonth() + + expect(result).toEqual({ + year: 2025, + month: 1, + week: 1 + }) +}) + +it('returns May 1st ISO week for 2025-05-01', () => { + const result = dayjs('2025-05-01').isoWeekOfMonth() + + expect(result).toEqual({ + year: 2025, + month: 5, + week: 1 + }) +}) + +it('returns May 2nd ISO week for 2025-05-11', () => { + const result = dayjs('2025-05-11').isoWeekOfMonth() + + expect(result).toEqual({ + year: 2025, + month: 5, + week: 2 + }) +}) + +it('returns May 3rd ISO week for 2025-05-12', () => { + const result = dayjs('2025-05-12').isoWeekOfMonth() + + expect(result).toEqual({ + year: 2025, + month: 5, + week: 3 + }) +}) + +it('returns May 5rd ISO week for 2025-06-01', () => { + const result = dayjs('2025-06-01').isoWeekOfMonth() + + expect(result).toEqual({ + year: 2025, + month: 5, + week: 5 + }) +}) + +it('returns July 1st ISO week for 2025-06-30 (across month)', () => { + const result = dayjs('2025-06-30').isoWeekOfMonth() + + expect(result).toEqual({ + year: 2025, + month: 7, + week: 1 + }) +}) diff --git a/types/plugin/isoWeekOfMonth.d.ts b/types/plugin/isoWeekOfMonth.d.ts new file mode 100644 index 000000000..1f8e85f88 --- /dev/null +++ b/types/plugin/isoWeekOfMonth.d.ts @@ -0,0 +1,16 @@ +import { PluginFunc } from 'dayjs' + +declare const plugin: PluginFunc +export = plugin + +declare module 'dayjs' { + interface IsoWeekOfMonthResult { + week: number + month: number + year: number + } + + interface Dayjs { + isoWeekOfMonth(): IsoWeekOfMonthResult + } +}