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:
M | datefmt.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);