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:
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
}