Skip to content

Commit

Permalink
feat(new tools): Date+Duration and Days Calculator
Browse files Browse the repository at this point in the history
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 #778, #584, #971
  • Loading branch information
sharevb committed Oct 27, 2024
1 parent 4c381f3 commit 8c09a05
Show file tree
Hide file tree
Showing 14 changed files with 1,736 additions and 6 deletions.
11 changes: 8 additions & 3 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ declare module '@vue/runtime-core' {
'CTextCopyable.demo': typeof import('./src/ui/c-text-copyable/c-text-copyable.demo.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']
DateDurationCalculator: typeof import('./src/tools/date-duration-calculator/date-duration-calculator.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']
Expand Down Expand Up @@ -131,22 +133,25 @@ 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']
NCheckboxGroup: typeof import('naive-ui')['NCheckboxGroup']
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']
NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
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']
NP: typeof import('naive-ui')['NP']
NScrollbar: typeof import('naive-ui')['NScrollbar']
NTag: typeof import('naive-ui')['NTag']
NSpace: typeof import('naive-ui')['NSpace']
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']
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"@tiptap/starter-kit": "2.1.6",
"@tiptap/vue-3": "2.0.3",
"@types/figlet": "^1.5.8",
"@types/luxon": "^3.4.2",
"@types/markdown-it": "^13.0.7",
"@vicons/material": "^0.12.0",
"@vicons/tabler": "^0.12.0",
Expand All @@ -54,11 +55,13 @@
"change-case": "^4.1.2",
"colord": "^2.9.3",
"composerize-ts": "^0.6.2",
"countries-and-timezones": "^3.7.2",
"country-code-lookup": "^0.1.0",
"cron-validator": "^1.3.1",
"cronstrue": "^2.26.0",
"crypto-js": "^4.1.1",
"date-fns": "^2.29.3",
"date-holidays": "^3.23.12",
"dompurify": "^3.0.6",
"duration-fns": "^3.0.2",
"email-normalizer": "^1.0.0",
Expand All @@ -74,6 +77,7 @@
"jwt-decode": "^3.1.2",
"libphonenumber-js": "^1.10.28",
"lodash": "^4.17.21",
"luxon": "^3.5.0",
"markdown-it": "^14.0.0",
"marked": "^10.0.0",
"mathjs": "^11.9.1",
Expand Down
100 changes: 99 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { describe, expect, it } from 'vitest';
import { addToDate } from './date-duration-calculator.service';

describe('date-duration-calculator', () => {
describe('addToDate', () => {
it('compute right values', () => {
expect(addToDate(new Date('2024-08-15T07:21:46Z'), '+1d 1m 20s')).to.deep.eq(
{
date: new Date('2024-08-16T07:23:06.000Z'),
durationPretty: '1d 1m 20s',
durationSeconds: 86480,
errors: [],
},
);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { computeDuration } from '../duration-calculator/duration-calculator.service';

export function addToDate(date: Date, durations: string) {
const { total, errors } = computeDuration(durations);

return {
errors,
date: new Date(date.getTime() + total.milliseconds),
durationSeconds: total.seconds,
durationPretty: total.prettified,
};
}
41 changes: 41 additions & 0 deletions src/tools/date-duration-calculator/date-duration-calculator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script setup lang="ts">
import { addToDate } from './date-duration-calculator.service';
const now = Date.now();
const inputReferenceDate = ref(now);
const inputDurations = ref('');
const resultDateAdder = computed(() => addToDate(new Date(inputReferenceDate.value), inputDurations.value));
const errorsDateAdder = computed(() => resultDateAdder.value.errors.join('\n'));
</script>

<template>
<div>
<c-card title="Date + Duration Calculator" mb-2>
<n-form-item label="Reference Date:" label-placement="left" mb-1>
<n-date-picker v-model:value="inputReferenceDate" type="datetime" />
</n-form-item>

<c-input-text
v-model:value="inputDurations"
multiline
rows="5"
label="Duration(s)"
placeholder="Please enter duration, one per line with optional sign"
mb-2
/>
<n-p>Supports: comment (# line), HH:MM:SS.FFF, 3d 1h 3s..., P4DT12H20M20.3S..</n-p>

<c-card v-if="errorsDateAdder" title="Lines errors">
<textarea-copyable :value="errorsDateAdder" />
</c-card>

<n-divider />

<input-copyable v-if="resultDateAdder" label="Result Date:" label-position="left" label-width="150px" :value="resultDateAdder.date.toString()" mb-1 />
<input-copyable v-if="resultDateAdder" label="Result ISO Date:" label-position="left" label-width="150px" :value="resultDateAdder.date.toISOString()" mb-1 />
<input-copyable v-if="resultDateAdder" label="Duration (seconds):" label-position="left" label-width="150px" :value="resultDateAdder.durationSeconds" mb-1 />
<input-copyable v-if="resultDateAdder" label="Duration:" label-position="left" label-width="150px" :value="resultDateAdder.durationPretty" mb-1 />
</c-card>
</div>
</template>
12 changes: 12 additions & 0 deletions src/tools/date-duration-calculator/index.ts
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: 'Date+Durations Calculator',
path: '/date-duration-calculator',
description: 'Add/substract durations from a specific date',
keywords: ['date', 'duration', 'addition', 'calculator'],
component: () => import('./date-duration-calculator.vue'),
icon: Calendar,
createdAt: new Date('2024-08-15'),
});
Loading

0 comments on commit 8c09a05

Please sign in to comment.