mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-05 13:57:10 -04:00
feat: add date difference calculator UI for issue #971
This commit is contained in:
parent
d3b32cc14e
commit
c7c6d1e4ad
7 changed files with 90 additions and 1 deletions
13
components.d.ts
vendored
13
components.d.ts
vendored
|
@ -65,6 +65,7 @@ declare module '@vue/runtime-core' {
|
||||||
CTooltip: typeof import('./src/ui/c-tooltip/c-tooltip.vue')['default']
|
CTooltip: typeof import('./src/ui/c-tooltip/c-tooltip.vue')['default']
|
||||||
'CTooltip.demo': typeof import('./src/ui/c-tooltip/c-tooltip.demo.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']
|
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']
|
'DemoHome.page': typeof import('./src/ui/demo/demo-home.page.vue')['default']
|
||||||
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
|
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
|
||||||
DeviceInformation: typeof import('./src/tools/device-information/device-information.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']
|
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']
|
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: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']
|
'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
|
||||||
IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default']
|
IconMdiChevronDown: typeof import('~icons/mdi/chevron-down')['default']
|
||||||
IconMdiChevronRight: typeof import('~icons/mdi/chevron-right')['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']
|
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
|
||||||
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.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']
|
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']
|
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
|
||||||
|
NCheckbox: typeof import('naive-ui')['NCheckbox']
|
||||||
NCode: typeof import('naive-ui')['NCode']
|
NCode: typeof import('naive-ui')['NCode']
|
||||||
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
|
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
|
||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||||
|
NDatePicker: typeof import('naive-ui')['NDatePicker']
|
||||||
NDivider: typeof import('naive-ui')['NDivider']
|
NDivider: typeof import('naive-ui')['NDivider']
|
||||||
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
NEllipsis: typeof import('naive-ui')['NEllipsis']
|
||||||
|
NForm: typeof import('naive-ui')['NForm']
|
||||||
NFormItem: typeof import('naive-ui')['NFormItem']
|
NFormItem: typeof import('naive-ui')['NFormItem']
|
||||||
NGi: typeof import('naive-ui')['NGi']
|
NGi: typeof import('naive-ui')['NGi']
|
||||||
NGrid: typeof import('naive-ui')['NGrid']
|
NGrid: typeof import('naive-ui')['NGrid']
|
||||||
NH1: typeof import('naive-ui')['NH1']
|
NH1: typeof import('naive-ui')['NH1']
|
||||||
NH3: typeof import('naive-ui')['NH3']
|
NH3: typeof import('naive-ui')['NH3']
|
||||||
NIcon: typeof import('naive-ui')['NIcon']
|
NIcon: typeof import('naive-ui')['NIcon']
|
||||||
|
NInputGroup: typeof import('naive-ui')['NInputGroup']
|
||||||
|
NInputGroupLabel: typeof import('naive-ui')['NInputGroupLabel']
|
||||||
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
NInputNumber: typeof import('naive-ui')['NInputNumber']
|
||||||
NLabel: typeof import('naive-ui')['NLabel']
|
NLabel: typeof import('naive-ui')['NLabel']
|
||||||
NLayout: typeof import('naive-ui')['NLayout']
|
NLayout: typeof import('naive-ui')['NLayout']
|
||||||
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
|
||||||
NMenu: typeof import('naive-ui')['NMenu']
|
NMenu: typeof import('naive-ui')['NMenu']
|
||||||
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
NScrollbar: typeof import('naive-ui')['NScrollbar']
|
||||||
|
NSlider: typeof import('naive-ui')['NSlider']
|
||||||
NSpin: typeof import('naive-ui')['NSpin']
|
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']
|
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']
|
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']
|
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']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
RsaKeyPairGenerator: typeof import('./src/tools/rsa-key-pair-generator/rsa-key-pair-generator.vue')['default']
|
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']
|
SlugifyString: typeof import('./src/tools/slugify-string/slugify-string.vue')['default']
|
||||||
SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default']
|
SpanCopyable: typeof import('./src/components/SpanCopyable.vue')['default']
|
||||||
SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default']
|
SqlPrettify: typeof import('./src/tools/sql-prettify/sql-prettify.vue')['default']
|
||||||
|
|
|
@ -92,6 +92,11 @@ tools:
|
||||||
button:
|
button:
|
||||||
copy: Copy
|
copy: Copy
|
||||||
refresh: Refresh
|
refresh: Refresh
|
||||||
|
|
||||||
|
days-calculator:
|
||||||
|
title: Days calculator
|
||||||
|
description: Find the number of days between two dates.
|
||||||
|
|
||||||
percentage-calculator:
|
percentage-calculator:
|
||||||
title: Percentage calculator
|
title: Percentage calculator
|
||||||
description: Easily calculate percentages from a value to another value, or from a percentage to a value.
|
description: Easily calculate percentages from a value to another value, or from a percentage to a value.
|
||||||
|
|
|
@ -91,6 +91,11 @@ tools:
|
||||||
button:
|
button:
|
||||||
copy: 复制
|
copy: 复制
|
||||||
refresh: 刷新
|
refresh: 刷新
|
||||||
|
|
||||||
|
days-calculator:
|
||||||
|
title: 天数计算器
|
||||||
|
description: 计算两个日期之间的天数。
|
||||||
|
|
||||||
percentage-calculator:
|
percentage-calculator:
|
||||||
title: 百分比计算器
|
title: 百分比计算器
|
||||||
description: 轻松计算从一个值到另一个值的百分比,或从百分比到值的百分比。
|
description: 轻松计算从一个值到另一个值的百分比,或从百分比到值的百分比。
|
||||||
|
|
16
src/tools/days-calculator/days-calculator.service.ts
Normal file
16
src/tools/days-calculator/days-calculator.service.ts
Normal file
|
@ -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` : '')
|
||||||
|
);
|
||||||
|
}
|
37
src/tools/days-calculator/days-calculator.vue
Normal file
37
src/tools/days-calculator/days-calculator.vue
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const startDate = ref<Date | null>(null);
|
||||||
|
const endDate = ref<Date | null>(null);
|
||||||
|
const includeEndDate = ref(false);
|
||||||
|
|
||||||
|
const calculatedDays = computed<string | null>(() => {
|
||||||
|
if (startDate.value && endDate.value) {
|
||||||
|
const start = new Date(startDate.value);
|
||||||
|
const end = new Date(endDate.value);
|
||||||
|
if (!Number.isNaN(start.getTime()) && !Number.isNaN(end.getTime())) {
|
||||||
|
const diff = Math.abs(end.getTime() - start.getTime());
|
||||||
|
const days = Math.ceil(diff / (1000 * 60 * 60 * 24));
|
||||||
|
return (includeEndDate.value ? days + 1 : days).toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<n-form>
|
||||||
|
<div w-full flex gap-4>
|
||||||
|
<n-form-item label="Start Date">
|
||||||
|
<n-date-picker v-model:value="startDate" type="date" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="End Date">
|
||||||
|
<n-date-picker v-model:value="endDate" type="date" />
|
||||||
|
</n-form-item>
|
||||||
|
</div>
|
||||||
|
<n-form-item label="Include end date in calculation (1 day is added)" label-placement="left">
|
||||||
|
<n-checkbox v-model:checked="includeEndDate" />
|
||||||
|
</n-form-item>
|
||||||
|
</n-form>
|
||||||
|
<c-input-text label="Calculated days" :value="calculatedDays" readonly />
|
||||||
|
</div>
|
||||||
|
</template>
|
12
src/tools/days-calculator/index.ts
Normal file
12
src/tools/days-calculator/index.ts
Normal file
|
@ -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,
|
||||||
|
});
|
|
@ -52,6 +52,7 @@ import { tool as dateTimeConverter } from './date-time-converter';
|
||||||
import { tool as deviceInformation } from './device-information';
|
import { tool as deviceInformation } from './device-information';
|
||||||
import { tool as cypher } from './encryption';
|
import { tool as cypher } from './encryption';
|
||||||
import { tool as etaCalculator } from './eta-calculator';
|
import { tool as etaCalculator } from './eta-calculator';
|
||||||
|
import { tool as daysCalculator } from './days-calculator';
|
||||||
import { tool as percentageCalculator } from './percentage-calculator';
|
import { tool as percentageCalculator } from './percentage-calculator';
|
||||||
import { tool as gitMemo } from './git-memo';
|
import { tool as gitMemo } from './git-memo';
|
||||||
import { tool as hashText } from './hash-text';
|
import { tool as hashText } from './hash-text';
|
||||||
|
@ -156,7 +157,7 @@ export const toolsByCategory: ToolCategory[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Math',
|
name: 'Math',
|
||||||
components: [mathEvaluator, etaCalculator, percentageCalculator],
|
components: [mathEvaluator, etaCalculator, percentageCalculator, daysCalculator],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Measurement',
|
name: 'Measurement',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue