work-time-calculator/src/main.ts

110 lines
3.8 KiB
TypeScript

import chalk from 'chalk';
import dayjs, { Dayjs } from 'dayjs';
import * as readline from 'readline/promises';
import { formatDuration, formatTimestamp, getHoursRoundedStr } from './format.js';
import { Duration } from 'dayjs/plugin/duration';
import { parseDuration, parseTimestamp } from './parse.js';
const { log, error } = console;
const defaultStartTime = '08:00';
const lunchBreakDuration = dayjs.duration({ minutes: 30 });
const defaultWorkDayDuration = dayjs.duration({ hours: 7, minutes: 30 });
const main = async () => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let started: Dayjs | undefined = undefined;
try {
// Get work day duration
let workDayDuration: Duration | undefined = undefined;
const durationAnswer = await rl.question(
`How long is your work day today, excluding the lunch break? [${formatDuration(defaultWorkDayDuration)}] `,
);
if (durationAnswer !== '') {
workDayDuration = parseDuration(durationAnswer);
if (workDayDuration.asMinutes() <= 0) {
error(
chalk.red(
`Failed to parse ${durationAnswer} to duration, using default work day duration ${defaultWorkDayDuration}`,
),
);
workDayDuration = undefined;
}
}
if (!workDayDuration) {
workDayDuration = defaultWorkDayDuration;
}
// Calculate worked time
const startTimeAnswer = await rl.question(`What time did you start work today? [${defaultStartTime}] `);
if (startTimeAnswer !== '') {
started = parseTimestamp(startTimeAnswer);
if (!started.isValid()) {
error(
chalk.red(
`Failed to parse ${startTimeAnswer} to time, using default start time ${defaultStartTime}`,
),
);
}
}
if (!started?.isValid()) {
started = parseTimestamp(defaultStartTime);
}
let stopped: Dayjs | undefined = undefined;
const stoppedAnswer = await rl.question(
"What time did you stop working (leave empty if you didn't stop yet)? ",
);
if (stoppedAnswer === '') {
stopped = dayjs();
} else {
stopped = parseTimestamp(stoppedAnswer);
if (!stopped.isValid()) {
error(`Failed to parse ${stoppedAnswer} to time, using current time`);
stopped = dayjs();
}
}
let worked = dayjs.duration(stopped.diff(started));
if ((await rl.question('Did you have a lunch break? [Y/n] ')).toLowerCase() !== 'n') {
worked = worked.subtract(lunchBreakDuration);
}
// Calculate unlogged time
let unLogged: Duration | undefined = undefined;
let loggedAnswer = await rl.question('How many hours did you log already? [00:00] ');
if (loggedAnswer === '') {
loggedAnswer = '00:00';
}
const logged = parseDuration(loggedAnswer);
const unLoggedDuration = workDayDuration.subtract(logged);
if (unLoggedDuration.asMinutes() > 0) {
unLogged = unLoggedDuration;
}
// Log result
log();
log('Started working at', formatTimestamp(started));
log('Stopped working at', formatTimestamp(stopped));
log('Total worked today:', chalk.green(formatDuration(worked)), chalk.yellow(getHoursRoundedStr(worked)));
log(
'Unlogged today:',
unLogged
? `${chalk.red(formatDuration(unLogged))} ${chalk.yellow(getHoursRoundedStr(unLogged))}`
: chalk.green('none'),
);
} finally {
rl.close();
}
};
main();