-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(new tool): Week Numbers Converter
- Loading branch information
Showing
6 changed files
with
122 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { Calendar } from '@vicons/tabler'; | ||
import { defineTool } from '../tool'; | ||
|
||
export const tool = defineTool({ | ||
name: 'Week Numbers Converter', | ||
path: '/week-number-converter', | ||
description: 'Compute Week Number in Year/Month vs Date', | ||
keywords: ['week', 'month', 'number', 'converter'], | ||
component: () => import('./week-number-converter.vue'), | ||
icon: Calendar, | ||
createdAt: new Date('2024-08-15'), | ||
}); |
20 changes: 20 additions & 0 deletions
20
src/tools/week-number-converter/week-number-converter.service.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { describe, expect, it } from 'vitest'; | ||
import { getWeekOfMonth } from 'date-fns'; | ||
import { getFirstMondayFromISOWeek, getFirstMondayFromMonthWeek } from './week-number-converter.service'; | ||
|
||
describe('week-number-converter', () => { | ||
describe('getFirstMondayFromISOWeek', () => { | ||
it('return right monday date from week number', () => { | ||
expect(getFirstMondayFromISOWeek(11, 2022).toDateString()).toBe('Mon Mar 14 2022'); | ||
expect(getFirstMondayFromISOWeek(1, 2023).toDateString()).toBe('Mon Jan 02 2023'); | ||
expect(getFirstMondayFromISOWeek(53, 2026).toDateString()).toBe('Mon Dec 28 2026'); | ||
}); | ||
}); | ||
describe('getFirstMondayFromMonthWeek', () => { | ||
it('return right date from month week number', () => { | ||
expect(getFirstMondayFromMonthWeek(getWeekOfMonth(new Date('2022-03-14')), 3, 2022).toDateString()).toBe('Mon Mar 14 2022'); | ||
expect(getFirstMondayFromMonthWeek(getWeekOfMonth(new Date('2023-01-02')), 1, 2023).toDateString()).toBe('Mon Jan 02 2023'); | ||
expect(getFirstMondayFromMonthWeek(getWeekOfMonth(new Date('2026-12-28')), 12, 2026).toDateString()).toBe('Mon Dec 28 2026'); | ||
}); | ||
}); | ||
}); |
15 changes: 15 additions & 0 deletions
15
src/tools/week-number-converter/week-number-converter.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Returns the first day (Monday) of the specified week | ||
|
||
// Year defaults to the current local calendar year | ||
export function getFirstMondayFromISOWeek(weekInYear: number, year = new Date().getFullYear()) { | ||
const d = new Date(year, 0, 4); | ||
d.setDate(d.getDate() - (d.getDay() || 7) + 1 + 7 * (weekInYear - 1)); | ||
return d; | ||
} | ||
export function getFirstMondayFromMonthWeek(weekInMonth: number, month = new Date().getMonth() + 1, year = new Date().getFullYear()) { | ||
const d = new Date(year, month - 1, 4); | ||
const day = d.getDay() || 7; | ||
d.setDate(d.getDate() - day + 1); | ||
d.setDate(d.getDate() + 7 * (weekInMonth - 1)); | ||
return d; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
<script setup lang="ts"> | ||
import { getWeek, getWeekOfMonth } from 'date-fns'; | ||
import { getFirstMondayFromISOWeek, getFirstMondayFromMonthWeek } from './week-number-converter.service'; | ||
const now = new Date(); | ||
const inputDate = ref(now.getTime()); | ||
const outputWeekInMonth = computed(() => getWeekOfMonth(inputDate.value)); | ||
const outputWeekInYear = computed(() => getWeek(inputDate.value)); | ||
const inputWeekInMonth = ref({ | ||
week: getWeekOfMonth(now), | ||
month: now.getMonth() + 1, | ||
year: now.getFullYear(), | ||
}); | ||
const outputWeekInMonthMonday = computed(() => getFirstMondayFromMonthWeek(inputWeekInMonth.value.week, inputWeekInMonth.value.month, inputWeekInMonth.value.year)); | ||
const inputWeekInYear = ref({ | ||
week: getWeek(now), | ||
year: now.getFullYear(), | ||
}); | ||
const outputWeekInYearMonday = computed(() => getFirstMondayFromISOWeek(inputWeekInYear.value.week, inputWeekInYear.value.year)); | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<c-card title="Date to Week numbers" mb-2> | ||
<n-form-item label="Date:" label-placement="left"> | ||
<n-date-picker v-model:value="inputDate" type="date" /> | ||
</n-form-item> | ||
|
||
<n-divider /> | ||
|
||
<input-copyable readonly label="Week in Year:" label-position="left" label-width="120px" :value="outputWeekInYear" mb-1 /> | ||
<input-copyable readonly label="Week in Month:" label-position="left" label-width="120px" :value="outputWeekInMonth" mb-1 /> | ||
</c-card> | ||
<c-card title="Year Week Number to Date" mb-2> | ||
<div flex items-baseline gap-2> | ||
<n-form-item label="Week in Year:" label-placement="left" flex-1> | ||
<n-input-number v-model:value="inputWeekInYear.week" :min="1" :max="53" /> | ||
</n-form-item> | ||
<n-form-item label="Year:" label-placement="left" flex-1> | ||
<n-input-number v-model:value="inputWeekInYear.year" /> | ||
</n-form-item> | ||
</div> | ||
|
||
<n-divider /> | ||
|
||
<input-copyable readonly label="First Monday" label-position="left" :value="outputWeekInYearMonday" /> | ||
</c-card> | ||
<c-card title="Month Week Number to Date" mb-2> | ||
<div flex items-baseline gap-2> | ||
<n-form-item label="Week in Month:" label-placement="left" flex-1> | ||
<n-input-number v-model:value="inputWeekInMonth.week" :min="1" :max="5" /> | ||
</n-form-item> | ||
<n-form-item label="Month:" label-placement="left" flex-1> | ||
<n-input-number v-model:value="inputWeekInMonth.month" :min="1" :max="12" /> | ||
</n-form-item> | ||
<n-form-item label="Year:" label-placement="left" flex-1> | ||
<n-input-number v-model:value="inputWeekInMonth.year" /> | ||
</n-form-item> | ||
</div> | ||
|
||
<n-divider /> | ||
|
||
<input-copyable readonly label="First Monday" label-position="left" :value="outputWeekInMonthMonday" /> | ||
</c-card> | ||
</div> | ||
</template> |