From 699f32747a19d1489bf5dae930e33c39dd496d0f Mon Sep 17 00:00:00 2001 From: sharevb Date: Wed, 2 Oct 2024 22:31:47 +0200 Subject: [PATCH] feat(new tool): Week Numbers Converter --- components.d.ts | 7 +- src/tools/index.ts | 2 + src/tools/week-number-converter/index.ts | 12 ++++ .../week-number-converter.service.test.ts | 20 ++++++ .../week-number-converter.service.ts | 15 ++++ .../week-number-converter.vue | 69 +++++++++++++++++++ 6 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 src/tools/week-number-converter/index.ts create mode 100644 src/tools/week-number-converter/week-number-converter.service.test.ts create mode 100644 src/tools/week-number-converter/week-number-converter.service.ts create mode 100644 src/tools/week-number-converter/week-number-converter.vue diff --git a/components.d.ts b/components.d.ts index 3e65c3cc..7b5c4700 100644 --- a/components.d.ts +++ b/components.d.ts @@ -130,19 +130,19 @@ declare module '@vue/runtime-core' { MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] - NCheckbox: typeof import('naive-ui')['NCheckbox'] NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] NConfigProvider: typeof import('naive-ui')['NConfigProvider'] + NDatePicker: typeof import('naive-ui')['NDatePicker'] NDivider: typeof import('naive-ui')['NDivider'] NEllipsis: typeof import('naive-ui')['NEllipsis'] + NFormItem: typeof import('naive-ui')['NFormItem'] NH1: typeof import('naive-ui')['NH1'] NH3: typeof import('naive-ui')['NH3'] NIcon: typeof import('naive-ui')['NIcon'] + NInputNumber: typeof import('naive-ui')['NInputNumber'] NLayout: typeof import('naive-ui')['NLayout'] NLayoutSider: typeof import('naive-ui')['NLayoutSider'] NMenu: typeof import('naive-ui')['NMenu'] - NSpace: typeof import('naive-ui')['NSpace'] - NTable: typeof import('naive-ui')['NTable'] NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] @@ -185,6 +185,7 @@ declare module '@vue/runtime-core' { UserAgentParser: typeof import('./src/tools/user-agent-parser/user-agent-parser.vue')['default'] UserAgentResultCards: typeof import('./src/tools/user-agent-parser/user-agent-result-cards.vue')['default'] UuidGenerator: typeof import('./src/tools/uuid-generator/uuid-generator.vue')['default'] + WeekNumberConverter: typeof import('./src/tools/week-number-converter/week-number-converter.vue')['default'] WifiQrCodeGenerator: typeof import('./src/tools/wifi-qr-code-generator/wifi-qr-code-generator.vue')['default'] XmlFormatter: typeof import('./src/tools/xml-formatter/xml-formatter.vue')['default'] XmlToJson: typeof import('./src/tools/xml-to-json/xml-to-json.vue')['default'] diff --git a/src/tools/index.ts b/src/tools/index.ts index 388cfaf4..38b7eb39 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -2,6 +2,7 @@ import { tool as base64FileConverter } from './base64-file-converter'; import { tool as base64StringConverter } from './base64-string-converter'; import { tool as basicAuthGenerator } from './basic-auth-generator'; import { tool as emailNormalizer } from './email-normalizer'; +import { tool as weekNumberConverter } from './week-number-converter'; import { tool as asciiTextDrawer } from './ascii-text-drawer'; @@ -116,6 +117,7 @@ export const toolsByCategory: ToolCategory[] = [ xmlToJson, jsonToXml, markdownToHtml, + weekNumberConverter, ], }, { diff --git a/src/tools/week-number-converter/index.ts b/src/tools/week-number-converter/index.ts new file mode 100644 index 00000000..8adcb4ed --- /dev/null +++ b/src/tools/week-number-converter/index.ts @@ -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'), +}); diff --git a/src/tools/week-number-converter/week-number-converter.service.test.ts b/src/tools/week-number-converter/week-number-converter.service.test.ts new file mode 100644 index 00000000..20e0b901 --- /dev/null +++ b/src/tools/week-number-converter/week-number-converter.service.test.ts @@ -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'); + }); + }); +}); diff --git a/src/tools/week-number-converter/week-number-converter.service.ts b/src/tools/week-number-converter/week-number-converter.service.ts new file mode 100644 index 00000000..74d3a1ba --- /dev/null +++ b/src/tools/week-number-converter/week-number-converter.service.ts @@ -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; +} diff --git a/src/tools/week-number-converter/week-number-converter.vue b/src/tools/week-number-converter/week-number-converter.vue new file mode 100644 index 00000000..9dcdcf0a --- /dev/null +++ b/src/tools/week-number-converter/week-number-converter.vue @@ -0,0 +1,69 @@ + + +