From c49ceace5cb14d9c2ea3f836dc73d7c31d88a738 Mon Sep 17 00:00:00 2001 From: Jonathan Delgado Date: Thu, 13 Jul 2023 09:44:23 -0400 Subject: [PATCH] feat: Add flag --epoch, --epoch-ms and --time-zone --- README.md | 9 +++++++-- crontab.ts | 47 ++++++++++++++++++++++++++++++++++++++++++++++ ndate.ts | 55 ++++++++++++++++++++++++++++++++++++++---------------- 3 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 crontab.ts diff --git a/README.md b/README.md index db20579..a5de3c3 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ Date format to console. ```shell Usage: ndate [-] [--zero] [--date-style ] [--time-style ] - [--local ] [--json] [--date ] [--help] [-j] [-d ] - [-l ] [-z] [-h] + [--time-zone] [--local ] [--json] [--epoch] [--epoch-ms] [--date ] + [--help] [-j] [-d ] [-l ] [-z] [-h] ``` Please install with deno: @@ -20,6 +20,11 @@ Samples use: ndate # Tuesday, October 11, 2022 at 5:59:37 PM Chile Summer Time ndate --local es-CL # martes, 11 de octubre de 2022, 17:59:14 hora de verano de Chile ndate --local en-CL # Tuesday, October 11, 2022 at 5:59:37 PM Chile Summer Time +ndate --time-zone Asia/Tokyo --local en-US # Thursday, July 13, 2023 at 6:46:21 AM Japan Standard Time +LANG=en-US ndate --time-zone Asia/Tokyo # Thursday, July 13, 2023 at 6:46:21 AM Japan Standard Time +LANG=en-US TZ=Asia/Tokyo ndate # Thursday, July 13, 2023 at 6:46:21 AM Japan Standard Time echo 2022-10-12T05:39:19.678Z | ndate - # Wednesday, October 12, 2022 at 2:39:19 AM Chile Summer Time ndate -j # 2022-10-12T05:40:33.246Z +ndate --epoch # 1689255846 +ndate --epoch-ms # 1689255823663 ``` diff --git a/crontab.ts b/crontab.ts new file mode 100644 index 0000000..613ec45 --- /dev/null +++ b/crontab.ts @@ -0,0 +1,47 @@ +const exp = /^((?@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(?@every (?((\d+)(ns|us|µs|ms|s|m|h))+))|(?(?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*))))$/ + +const lines = [ + '20 16 * * *', + '0 0 0 1 1', + '0 0 0 1 1,2', + '0 0 0 1 1,2,3', + '0 0 * * 1/4', + '0 0 * 0 1-4', + '0 * * * 2/4', + '* * * * *', + // '@annually', + // '@yearly', + // '@monthly', + // '@weekly', + // '@daily', + // '@hourly', + // '@reboot', + // '@every 5s', + // '@every 20h30m', +] + +export class Cron { + constructor( + readonly minute: string, + readonly hour: string, + readonly day_month: string, + readonly month: string, + readonly day_week: string, + ) { } + static parse(value: string) { + const res = exp.exec(value)?.groups + if (typeof res?.cron === 'string') { + return new Cron( + res.cron_minute, + res.cron_hour, + res.cron_day_month, + res.cron_month, + res.cron_day_week, + ) + } + } +} + +for (const l of lines) { + console.log(l, Cron.parse(l)) +} \ No newline at end of file diff --git a/ndate.ts b/ndate.ts index 981830d..4df2c49 100644 --- a/ndate.ts +++ b/ndate.ts @@ -14,22 +14,40 @@ const dateParse = (val: string): Date => { let dateStyle: DateStyle = 'full'; let timeStyle: TimeStyle = 'full'; -let newLine = true; +let insertFinalNewLine = true; let local: string | undefined; +let timeZone: string | undefined; let date = new Date(); -let json = false; -let stdinRedeable = false; +let outputAsEpoch = false; +let outputAsEpochMS = false; +let outputAsJSON = false; +let stdinReadable = false; let showHelp = false; +let crontab: string | undefined; -const transformOptions: Record string | undefined) => void> = { - '-': () => { stdinRedeable = true }, - '--zero': () => { newLine = false; }, - '--date-style': (next) => { dateStyle = toDateStyle(next()) ?? 'full' }, - '--time-style': (next) => { timeStyle = toTimeStyle(next()) ?? 'full' }, - '--local': (next) => { local = next() }, - '--json': () => { json = true }, - '--date': (next) => { - const v = next(); +const parseCrontab = (str: string) => { + const res = /^((?@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(?@every ((?\d+)(?ns|us|µs|ms|s|m|h))+)|(?(?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*)) (?((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*))))$/.exec(str) + + if (!res) return null + + if (res.groups?.predefined) + return { + predefined: res.groups.predefined + } +} + +const transformOptions: Record string | undefined) => void> = { + '-': () => { stdinReadable = true }, + '--zero': () => { insertFinalNewLine = false; }, + '--date-style': (nextArgument) => { dateStyle = toDateStyle(nextArgument()) ?? 'full' }, + '--time-style': (nextArgument) => { timeStyle = toTimeStyle(nextArgument()) ?? 'full' }, + '--time-zone': (nextArgument)=>{ timeZone = nextArgument() }, + '--local': (nextArgument) => { local = nextArgument() }, + '--json': () => { outputAsJSON = true }, + '--epoch': () => { outputAsEpoch = true }, + '--epoch-ms': () => { outputAsEpochMS = true }, + '--date': (nextArgument) => { + const v = nextArgument(); if (v) { date = dateParse(v); } @@ -97,18 +115,23 @@ const run = async () => { return; } - if (stdinRedeable) { + if (stdinReadable) { const buff = new Uint8Array(256); await Deno.stdin.read(buff); const text = new TextDecoder().decode(buff.subarray(0, buff.findIndex(p => p === 0))).trim(); date = dateParse(text); } - const dateStr = json ? date.toJSON() : date.toLocaleString(local, { dateStyle, timeStyle }); + const toOutput = () => { + if (outputAsEpochMS) return Math.floor(date.getTime()).toString(); + if (outputAsEpoch) return Math.floor(date.getTime() / 1000).toString(); + if (outputAsJSON) return date.toJSON() + return date.toLocaleString(local, { dateStyle, timeStyle, timeZone }); + } - Deno.stdout.write(new TextEncoder().encode(dateStr)) + Deno.stdout.write(new TextEncoder().encode(toOutput())) - if (newLine) Deno.stdout.write( + if (insertFinalNewLine) Deno.stdout.write( new TextEncoder().encode(`\n`) ) }