Skip to content

Commit dec2e31

Browse files
committed
feat(new tools): Date+Duration and Days Calculator
Allows computing specific date + some durations Allows computing Date interval with many options (include end date, select week days, holidays, business time) and output many statistics Fix CorentinTh#778, CorentinTh#584, CorentinTh#971
1 parent 4c381f3 commit dec2e31

14 files changed

+1736
-6
lines changed

components.d.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ declare module '@vue/runtime-core' {
6464
'CTextCopyable.demo': typeof import('./src/ui/c-text-copyable/c-text-copyable.demo.vue')['default']
6565
CTooltip: typeof import('./src/ui/c-tooltip/c-tooltip.vue')['default']
6666
'CTooltip.demo': typeof import('./src/ui/c-tooltip/c-tooltip.demo.vue')['default']
67+
DateDurationCalculator: typeof import('./src/tools/date-duration-calculator/date-duration-calculator.vue')['default']
6768
DateTimeConverter: typeof import('./src/tools/date-time-converter/date-time-converter.vue')['default']
69+
DaysCalculator: typeof import('./src/tools/days-calculator/days-calculator.vue')['default']
6870
'DemoHome.page': typeof import('./src/ui/demo/demo-home.page.vue')['default']
6971
DemoWrapper: typeof import('./src/ui/demo/demo-wrapper.vue')['default']
7072
DeviceInformation: typeof import('./src/tools/device-information/device-information.vue')['default']
@@ -131,22 +133,25 @@ declare module '@vue/runtime-core' {
131133
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
132134
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
133135
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
136+
NCheckbox: typeof import('naive-ui')['NCheckbox']
137+
NCheckboxGroup: typeof import('naive-ui')['NCheckboxGroup']
134138
NCode: typeof import('naive-ui')['NCode']
135139
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
136140
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
141+
NDatePicker: typeof import('naive-ui')['NDatePicker']
137142
NDivider: typeof import('naive-ui')['NDivider']
138143
NEllipsis: typeof import('naive-ui')['NEllipsis']
139-
NGi: typeof import('naive-ui')['NGi']
140-
NGrid: typeof import('naive-ui')['NGrid']
144+
NFormItem: typeof import('naive-ui')['NFormItem']
141145
NH1: typeof import('naive-ui')['NH1']
142146
NH3: typeof import('naive-ui')['NH3']
143147
NIcon: typeof import('naive-ui')['NIcon']
148+
NInputNumber: typeof import('naive-ui')['NInputNumber']
144149
NLayout: typeof import('naive-ui')['NLayout']
145150
NLayoutSider: typeof import('naive-ui')['NLayoutSider']
146151
NMenu: typeof import('naive-ui')['NMenu']
147152
NP: typeof import('naive-ui')['NP']
148153
NScrollbar: typeof import('naive-ui')['NScrollbar']
149-
NTag: typeof import('naive-ui')['NTag']
154+
NSpace: typeof import('naive-ui')['NSpace']
150155
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
151156
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
152157
PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default']

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
"@tiptap/starter-kit": "2.1.6",
4545
"@tiptap/vue-3": "2.0.3",
4646
"@types/figlet": "^1.5.8",
47+
"@types/luxon": "^3.4.2",
4748
"@types/markdown-it": "^13.0.7",
4849
"@vicons/material": "^0.12.0",
4950
"@vicons/tabler": "^0.12.0",
@@ -54,11 +55,13 @@
5455
"change-case": "^4.1.2",
5556
"colord": "^2.9.3",
5657
"composerize-ts": "^0.6.2",
58+
"countries-and-timezones": "^3.7.2",
5759
"country-code-lookup": "^0.1.0",
5860
"cron-validator": "^1.3.1",
5961
"cronstrue": "^2.26.0",
6062
"crypto-js": "^4.1.1",
6163
"date-fns": "^2.29.3",
64+
"date-holidays": "^3.23.12",
6265
"dompurify": "^3.0.6",
6366
"duration-fns": "^3.0.2",
6467
"email-normalizer": "^1.0.0",
@@ -74,6 +77,7 @@
7477
"jwt-decode": "^3.1.2",
7578
"libphonenumber-js": "^1.10.28",
7679
"lodash": "^4.17.21",
80+
"luxon": "^3.5.0",
7781
"markdown-it": "^14.0.0",
7882
"marked": "^10.0.0",
7983
"mathjs": "^11.9.1",

pnpm-lock.yaml

Lines changed: 99 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { addToDate } from './date-duration-calculator.service';
3+
4+
describe('date-duration-calculator', () => {
5+
describe('addToDate', () => {
6+
it('compute right values', () => {
7+
expect(addToDate(new Date('2024-08-15T07:21:46Z'), '+1d 1m 20s')).to.deep.eq(
8+
{
9+
date: new Date('2024-08-16T07:23:06.000Z'),
10+
durationPretty: '1d 1m 20s',
11+
durationSeconds: 86480,
12+
errors: [],
13+
},
14+
);
15+
});
16+
});
17+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { computeDuration } from '../duration-calculator/duration-calculator.service';
2+
3+
export function addToDate(date: Date, durations: string) {
4+
const { total, errors } = computeDuration(durations);
5+
6+
return {
7+
errors,
8+
date: new Date(date.getTime() + total.milliseconds),
9+
durationSeconds: total.seconds,
10+
durationPretty: total.prettified,
11+
};
12+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<script setup lang="ts">
2+
import { addToDate } from './date-duration-calculator.service';
3+
4+
const now = Date.now();
5+
6+
const inputReferenceDate = ref(now);
7+
const inputDurations = ref('');
8+
const resultDateAdder = computed(() => addToDate(new Date(inputReferenceDate.value), inputDurations.value));
9+
const errorsDateAdder = computed(() => resultDateAdder.value.errors.join('\n'));
10+
</script>
11+
12+
<template>
13+
<div>
14+
<c-card title="Date + Duration Calculator" mb-2>
15+
<n-form-item label="Reference Date:" label-placement="left" mb-1>
16+
<n-date-picker v-model:value="inputReferenceDate" type="datetime" />
17+
</n-form-item>
18+
19+
<c-input-text
20+
v-model:value="inputDurations"
21+
multiline
22+
rows="5"
23+
label="Duration(s)"
24+
placeholder="Please enter duration, one per line with optional sign"
25+
mb-2
26+
/>
27+
<n-p>Supports: comment (# line), HH:MM:SS.FFF, 3d 1h 3s..., P4DT12H20M20.3S..</n-p>
28+
29+
<c-card v-if="errorsDateAdder" title="Lines errors">
30+
<textarea-copyable :value="errorsDateAdder" />
31+
</c-card>
32+
33+
<n-divider />
34+
35+
<input-copyable v-if="resultDateAdder" label="Result Date:" label-position="left" label-width="150px" :value="resultDateAdder.date.toString()" mb-1 />
36+
<input-copyable v-if="resultDateAdder" label="Result ISO Date:" label-position="left" label-width="150px" :value="resultDateAdder.date.toISOString()" mb-1 />
37+
<input-copyable v-if="resultDateAdder" label="Duration (seconds):" label-position="left" label-width="150px" :value="resultDateAdder.durationSeconds" mb-1 />
38+
<input-copyable v-if="resultDateAdder" label="Duration:" label-position="left" label-width="150px" :value="resultDateAdder.durationPretty" mb-1 />
39+
</c-card>
40+
</div>
41+
</template>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Calendar } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Date+Durations Calculator',
6+
path: '/date-duration-calculator',
7+
description: 'Add/substract durations from a specific date',
8+
keywords: ['date', 'duration', 'addition', 'calculator'],
9+
component: () => import('./date-duration-calculator.vue'),
10+
icon: Calendar,
11+
createdAt: new Date('2024-08-15'),
12+
});

0 commit comments

Comments
 (0)