datefmt

format unix timestamps over stdin
git clone git://jb55.com/datefmt
Log | Files | Refs | README | LICENSE

commit 4a6628c744ccce5e3bb8fa7e02419c0f59a40247
parent 531e2369b30db01593bd17840fe399802a757791
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 20 Oct 2022 11:26:03 -0700

Add --timeago timestamp formatting

Enables relative timestamp formatting (2h, etc.)

Changelog-Added: Add --timeago: relative timestamp formatting
Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
Mdatefmt.c | 50+++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 47 insertions(+), 3 deletions(-)

diff --git a/datefmt.c b/datefmt.c @@ -22,6 +22,7 @@ struct parser { int n_digits; int dir; int ms; + int timeago; const char *format; char digits[15]; }; @@ -79,9 +80,48 @@ static int time_matches(struct parser *parser, int64_t ts) return 1; } -static enum state doaction(int c, enum state new_state, struct parser *parser) +static void print_timeago(int64_t previous) +{ + time_t now = time(NULL); + + int ms_per_minute = 60 * 1000; + int ms_per_hour = ms_per_minute * 60; + int ms_per_day = ms_per_hour * 24; + int ms_per_month = ms_per_day * 30; + int ms_per_year = ms_per_day * 365; + + int elapsed = now - previous; + + if (elapsed < ms_per_minute) { + printf("%ds", elapsed / 1000); + } else if (elapsed < ms_per_hour) { + printf("%dm", elapsed / ms_per_minute); + } else if (elapsed < ms_per_day) { + printf("%dh", elapsed / ms_per_hour); + } else if (elapsed < ms_per_month) { + printf("%dd", elapsed / ms_per_day); + } else if (elapsed < ms_per_year) { + printf("%dmth", elapsed / ms_per_month); + } else { + printf("%dyr", elapsed / ms_per_year); + } +} + +static void print_time(const char *format, char *charbuf, int64_t ts, int timeago) { static char timebuf[128]; + + if (timeago) { + print_timeago(ts); + printf("%s", charbuf); + } else { + strftime(timebuf, sizeof(timebuf), format, localtime((time_t*)&ts)); + printf("%s%s", timebuf, charbuf); + } +} + +static enum state doaction(int c, enum state new_state, struct parser *parser) +{ char charbuf[2]; int64_t ts; @@ -99,8 +139,7 @@ static enum state doaction(int c, enum state new_state, struct parser *parser) ts = strtoll(parser->digits, NULL, 10); /* found date */ if (time_matches(parser, ts)) { - strftime(timebuf, sizeof(timebuf), parser->format, localtime((time_t*)&ts)); - printf("%s%s", timebuf, charbuf); + print_time(parser->format, charbuf, ts, parser->timeago); } else { print_rest(parser, charbuf, &new_state); } @@ -175,6 +214,7 @@ static void parser_init(struct parser *parser) parser->before = -1; parser->dir = 0; parser->ms = 0; + parser->timeago = 0; parser->n_digits = 0; parser->format = fmt? fmt : "%F %R"; } @@ -188,6 +228,7 @@ static void usage() { printf(" -p, --past only format timestamps in the past \n"); printf(" --version display version information and exit \n"); printf(" -m, --ms interpret timestamps as milliseconds instead of seconds \n"); + printf(" -t, --timeago custom format: show age of timestamp (1h, 2d, etc) \n"); printf("\n FORMAT\n a strftime format string, defaults to '%%F %%R'\n"); @@ -246,6 +287,9 @@ static void parse_arg(int *argc, char **argv, struct parser *parser) } else if (!strcmp("--ms", argv[0]) || !strcmp("-m", argv[0])) { parser->ms = 1; shift_arg(argc, argv); + } else if (!strcmp("--timeago", argv[0]) || !strcmp("-t", argv[0])) { + parser->timeago = 1; + shift_arg(argc, argv); } else { parser->format = (const char*)argv[0]; shift_arg(argc, argv);