diff --git a/components.d.ts b/components.d.ts
index e31119b3..a70b7f23 100644
--- a/components.d.ts
+++ b/components.d.ts
@@ -65,6 +65,7 @@ declare module '@vue/runtime-core' {
CTooltip: typeof import('./src/ui/c-tooltip/c-tooltip.vue')['default']
'CTooltip.demo': typeof import('./src/ui/c-tooltip/c-tooltip.demo.vue')['default']
DateTimeConverter: typeof import('./src/tools/date-time-converter/date-time-converter.vue')['default']
+ DaysCalculator: typeof import('./src/tools/days-calculator/days-calculator.vue')['default']
'DemoHome.page': typeof import('./src/ui/demo/demo-home.page.vue')['default']
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
@@ -89,6 +90,7 @@ declare module '@vue/runtime-core' {
HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default']
IbanValidatorAndParser: typeof import('./src/tools/iban-validator-and-parser/iban-validator-and-parser.vue')['default']
'IconMdi:brushVariant': typeof import('~icons/mdi/brush-variant')['default']
+ 'IconMdi:contentCopy': typeof import('~icons/mdi/content-copy')['default']
'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default']
IconMdiChevronRight: typeof import('~icons/mdi/chevron-right')['default']
@@ -126,25 +128,35 @@ declare module '@vue/runtime-core' {
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
+ NAlert: typeof import('naive-ui')['NAlert']
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
+ NCheckbox: typeof import('naive-ui')['NCheckbox']
NCode: typeof import('naive-ui')['NCode']
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']
+ NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
NH1: typeof import('naive-ui')['NH1']
NH3: typeof import('naive-ui')['NH3']
NIcon: typeof import('naive-ui')['NIcon']
+ NInputGroup: typeof import('naive-ui')['NInputGroup']
+ NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
NInputNumber: typeof import('naive-ui')['NInputNumber']
NLabel: typeof import('naive-ui')['NLabel']
NLayout: typeof import('naive-ui')['NLayout']
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
NMenu: typeof import('naive-ui')['NMenu']
NScrollbar: typeof import('naive-ui')['NScrollbar']
+ NSlider: typeof import('naive-ui')['NSlider']
NSpin: typeof import('naive-ui')['NSpin']
+ NStatistic: typeof import('naive-ui')['NStatistic']
+ NSwitch: typeof import('naive-ui')['NSwitch']
+ 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']
@@ -159,6 +171,7 @@ declare module '@vue/runtime-core' {
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default']
+ SafelinkDecoder: typeof import('./src/tools/safelink-decoder/safelink-decoder.vue')['default']
SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default']
SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default']
SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default']
diff --git a/locales/en.yml b/locales/en.yml
index 50d48af9..4cf3c232 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -92,6 +92,11 @@ tools:
button:
copy: Copy
refresh: Refresh
+
+ days-calculator:
+ title: Days calculator
+ description: Find the number of days between two dates.
+
percentage-calculator:
title: Percentage calculator
description: Easily calculate percentages from a value to another value, or from a percentage to a value.
diff --git a/locales/zh.yml b/locales/zh.yml
index 160fe1fa..221defb1 100644
--- a/locales/zh.yml
+++ b/locales/zh.yml
@@ -91,6 +91,11 @@ tools:
button:
copy: 复制
refresh: 刷新
+
+ days-calculator:
+ title: 天数计算器
+ description: 计算两个日期之间的天数。
+
percentage-calculator:
title: 百分比计算器
description: 轻松计算从一个值到另一个值的百分比,或从百分比到值的百分比。
diff --git a/src/tools/days-calculator/days-calculator.service.ts b/src/tools/days-calculator/days-calculator.service.ts
new file mode 100644
index 00000000..6c061a9d
--- /dev/null
+++ b/src/tools/days-calculator/days-calculator.service.ts
@@ -0,0 +1,16 @@
+import { formatDuration } from 'date-fns';
+
+export function formatMsDuration(duration: number) {
+ const ms = Math.floor(duration % 1000);
+ const secs = Math.floor(((duration - ms) / 1000) % 60);
+ const mins = Math.floor((((duration - ms) / 1000 - secs) / 60) % 60);
+ const hrs = Math.floor((((duration - ms) / 1000 - secs) / 60 - mins) / 60);
+
+ return (
+ formatDuration({
+ hours: hrs,
+ minutes: mins,
+ seconds: secs,
+ }) + (ms > 0 ? ` ${ms} ms` : '')
+ );
+}
diff --git a/src/tools/days-calculator/days-calculator.vue b/src/tools/days-calculator/days-calculator.vue
new file mode 100644
index 00000000..534b2e2e
--- /dev/null
+++ b/src/tools/days-calculator/days-calculator.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/tools/days-calculator/index.ts b/src/tools/days-calculator/index.ts
new file mode 100644
index 00000000..458ec819
--- /dev/null
+++ b/src/tools/days-calculator/index.ts
@@ -0,0 +1,12 @@
+import { CalendarPlus } from '@vicons/tabler';
+import { defineTool } from '../tool';
+import { translate } from '@/plugins/i18n.plugin';
+
+export const tool = defineTool({
+ name: translate('tools.days-calculator.title'),
+ path: '/days-calculator',
+ description: translate('tools.days-calculator.description'),
+ keywords: ['days', 'calculator', 'between', 'two', 'dates'],
+ component: () => import('./days-calculator.vue'),
+ icon: CalendarPlus,
+});
diff --git a/src/tools/index.ts b/src/tools/index.ts
index aa861c93..f3f47bb2 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -52,6 +52,7 @@ import { tool as dateTimeConverter } from './date-time-converter';
import { tool as deviceInformation } from './device-information';
import { tool as cypher } from './encryption';
import { tool as etaCalculator } from './eta-calculator';
+import { tool as daysCalculator } from './days-calculator';
import { tool as percentageCalculator } from './percentage-calculator';
import { tool as gitMemo } from './git-memo';
import { tool as hashText } from './hash-text';
@@ -156,7 +157,7 @@ export const toolsByCategory: ToolCategory[] = [
},
{
name: 'Math',
- components: [mathEvaluator, etaCalculator, percentageCalculator],
+ components: [mathEvaluator, etaCalculator, percentageCalculator, daysCalculator],
},
{
name: 'Measurement',