logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git
commit: 3f5c37ade3b274a4b5fb4414de9d01afaa08c653
parent 445d7356995342567674646f51dd37cb4effbcd8
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Fri, 11 Mar 2022 17:32:40 +0100

bin/date: Add support for setting a custom datetime

Diffstat:

Mbin/date.16+++++-
Mbin/date.c57++++++++++++++++++++++++++++++++++++++++++++++++---------
Mtest-bin/date16+++++++++++++---
3 files changed, 66 insertions(+), 13 deletions(-)

diff --git a/bin/date.1 b/bin/date.1 @@ -1,7 +1,7 @@ .\" Collection of Unix tools, comparable to coreutils .\" Copyright 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> .\" SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only -.Dd 2018-10-15 +.Dd 2022-03-11 .Dt DATE 1 .Os .Sh NAME @@ -10,6 +10,7 @@ .Sh SYNOPSIS .Nm .Op Fl u +.Op Fl d Ar datetime .Op Cm + Ns Ar format .Sh DESCRIPTION When @@ -17,6 +18,9 @@ When is invoked without arguments it displays the current datetime Otherwise, depending on the options specified, will print the datetime in a user-defined way. .Bl -tag -width Ds +.It Fl d Ar datetime +.Ar datetime +can contain the Unix timestamp (number of seconds before and after 1970-01-01T00:00:00Z) prefixed by an @ (at) symbol. .It Fl u Use UTC (coordinated universal time) instead of the local time. .El diff --git a/bin/date.c b/bin/date.c @@ -6,9 +6,34 @@ #include <errno.h> /* errno */ #include <locale.h> /* setlocale() */ #include <stdio.h> /* BUFSIZ, perror(), puts() */ -#include <stdlib.h> /* exit() */ +#include <stdlib.h> /* exit(), strtol() */ #include <time.h> /* time, localtime, tm, strftime */ #include <unistd.h> /* getopt(), optarg, optind */ +#include <errno.h> /* errno */ + +int +custom_datetime(time_t *now, char *optarg) +{ + if(optarg[0] == '@') { + optarg++; + errno = 0; + *now = (time_t)strtol(optarg, NULL, 10); + if(errno != 0) { + perror("strtol"); + return 0; + } + + return 1; + } + + return 0; +} + +void +usage() +{ + fprintf(stderr, "date [-u][-d datetime] [+format]\n"); +} int main(int argc, char *argv[]) @@ -22,23 +47,37 @@ main(int argc, char *argv[]) setlocale(LC_ALL, ""); - while((c = getopt(argc, argv, ":u")) != -1) + now = time(NULL); + if(now == (time_t)-1) + { + perror("time"); + exit(EXIT_FAILURE); + } + + while((c = getopt(argc, argv, ":d:u")) != -1) { switch(c) { + case 'd': /* Custom datetime */ + if(!custom_datetime(&now, optarg)) + { + return 1; + } + break; case 'u': /* UTC timezone */ uflag++; break; + case ':': + fprintf(stderr, "Error: Missing operand for option: '-%c'\n", optopt); + usage(); + return 1; + case '?': + fprintf(stderr, "Error: Unrecognised option: '-%c'\n", optopt); + usage(); + return 1; } } - now = time(NULL); - if(now == (time_t)-1) - { - perror("time"); - exit(EXIT_FAILURE); - } - if(uflag) { tm = gmtime(&now); diff --git a/test-bin/date b/test-bin/date @@ -38,16 +38,26 @@ utc_body() { atf_check -o "match:^[0-9]+$" ../bin/date -u '+%s' } +atf_test_case timestamp +timestamp_body() { + atf_check -o "inline:1970-01-01T00:00:00\n" ../bin/date -u -d @0 '+%FT%T' + atf_check -o "inline:1970-01-01T00:01:09\n" ../bin/date -u -d @69 '+%FT%T' + atf_check -o "inline:1969-12-31T23:58:51\n" ../bin/date -u -d @-69 '+%FT%T' +} + atf_init_test_cases() { cd "$(atf_get_srcdir)" || exit 1 . ../test_functions.sh atf_add_test_case noargs - atf_add_test_case epoch - atf_add_test_case rfc3339 atf_add_test_case empty - atf_add_test_case utc atf_add_test_case echolike atf_add_test_case devfull + + atf_add_test_case epoch + atf_add_test_case rfc3339 + atf_add_test_case utc + + atf_add_test_case timestamp }