diff --git a/src/tools/chronometer/chronometer.service.test.ts b/src/tools/chronometer/chronometer.service.test.ts new file mode 100644 index 00000000..5fdb3c72 --- /dev/null +++ b/src/tools/chronometer/chronometer.service.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from 'vitest'; +import { formatChronometerTime } from './chronometer.service'; + +describe('chronometer', () => { + describe('formatChronometerTime', () => { + it('format the elapsed time', () => { + expect(formatChronometerTime({ elapsed: 123456 })).toEqual('02:03.456'); + expect(formatChronometerTime({ elapsed: 123456, msPerUnit: 100 })).toEqual('03:25:45.600'); + expect(formatChronometerTime({ elapsed: 12345600 })).toEqual('03:25:45.600'); + }); + }); +}); diff --git a/src/tools/chronometer/chronometer.service.ts b/src/tools/chronometer/chronometer.service.ts new file mode 100644 index 00000000..a2e03b8a --- /dev/null +++ b/src/tools/chronometer/chronometer.service.ts @@ -0,0 +1,13 @@ +export function formatChronometerTime({ elapsed, msPerUnit = 1 }: { elapsed: number; msPerUnit?: number }) { + const elapsedMs = elapsed * msPerUnit; + + const ms = elapsedMs % 1000; + const secs = ((elapsedMs - ms) / 1000) % 60; + const mins = (((elapsedMs - ms) / 1000 - secs) / 60) % 60; + const hrs = (((elapsedMs - ms) / 1000 - secs) / 60 - mins) / 60; + const hrsString = hrs > 0 ? `${hrs.toString().padStart(2, '0')}:` : ''; + + return `${hrsString}${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}.${ms + .toString() + .padStart(3, '0')}`; +} diff --git a/src/tools/chronometer/chronometer.vue b/src/tools/chronometer/chronometer.vue new file mode 100644 index 00000000..2efcdc10 --- /dev/null +++ b/src/tools/chronometer/chronometer.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/tools/chronometer/index.ts b/src/tools/chronometer/index.ts new file mode 100644 index 00000000..424d03dc --- /dev/null +++ b/src/tools/chronometer/index.ts @@ -0,0 +1,11 @@ +import { TimerOutlined } from '@vicons/material'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Chronometer', + path: '/chronometer', + description: 'Monitor the duration of a thing. Basically a chronometer with simple chronometer features.', + keywords: ['chronometer', 'time', 'lap', 'duration', 'measure', 'pause', 'resume', 'stopwatch'], + component: () => import('./chronometer.vue'), + icon: TimerOutlined, +}); diff --git a/src/tools/index.ts b/src/tools/index.ts index fe9e01f9..eeed10c9 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -5,6 +5,7 @@ import { tool as base64Converter } from './base64-converter'; import { tool as bcrypt } from './bcrypt'; import { tool as bip39 } from './bip39-generator'; import { tool as caseConverter } from './case-converter'; +import { tool as chronometer } from './chronometer'; import { tool as colorConverter } from './color-converter'; import { tool as crontabGenerator } from './crontab-generator'; import { tool as dateTimeConverter } from './date-time-converter'; @@ -59,6 +60,11 @@ export const toolsByCategory: ToolCategory[] = [ icon: LockOpen, components: [mathEvaluator], }, + { + name: 'Measurement', + icon: LockOpen, + components: [chronometer], + }, { name: 'Text', icon: LockOpen,