commit: bf470569bee7ba1c15a604e143cb76286c8d13af
parent bc319721cd3aed7eae7abe3fa77d3cf72b2b9a0e
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sun, 20 Jul 2025 03:50:01 +0200
cmd/date: add support for long options
Diffstat:
M | cmd/date.c | 63 | +++++++++++++++++++++++++++++++++++++++++++++------------------ |
1 file changed, 45 insertions(+), 18 deletions(-)
diff --git a/cmd/date.c b/cmd/date.c
@@ -6,6 +6,7 @@
#define _POSIX_C_SOURCE 200809L
#define _XOPEN_SOURCE 700 // strptime is in XSI
+#include "../config.h" // HAS_*
#include "../libutils/datetime_parse.h" /* datetime_parse */
#include "../libutils/getopt_nolong.h"
@@ -18,6 +19,9 @@
#include <string.h> /* strerror */
#include <time.h> /* time, localtime, tm, strftime, strptime, clock_settime */
#include <unistd.h> /* getopt(), opt… */
+#ifdef HAS_GETOPT_LONG
+#include <getopt.h>
+#endif
const char *argv0 = "date";
@@ -152,7 +156,25 @@ main(int argc, char *argv[])
return 1;
}
+#ifdef HAS_GETOPT_LONG
+ // Strictly for GNUisms compatibility so no long-only options
+ // clang-format off
+ static struct option opts[] = {
+ {"date", required_argument, 0, 'd'},
+ {"iso-8601", optional_argument, 0, 'I'},
+ {"rfc-email", no_argument, 0, 'R'},
+ {"universal", no_argument, 0, 'u'},
+ {"utc", no_argument, 0, 'u'},
+ {0, 0, 0, 0},
+ };
+ // clang-format on
+
+ // Need + as first character to get POSIX-style option parsing
+ // Assume all getopt_long implementations support :: for optional args
+ for(int c = -1; (c = getopt_long(argc, argv, "+:d:f:I::jr:Ru", opts, NULL)) != -1;)
+#else
for(int c = -1; (c = getopt_nolong(argc, argv, ":d:f:I:jr:Ru")) != -1;)
+#endif
{
const char *errstr = NULL;
switch(c)
@@ -238,26 +260,31 @@ main(int argc, char *argv[])
tzset();
break;
case 'I': /* ISO 8601 */
- /* note: %:z (±ZZ:ZZ) and %N (nanoseconds) are date(1) GNU-isms absent from C libraries including glibc */
- switch(optarg[0])
+ if(optarg)
{
- case 'h': // hours
- format = "%Y-%m-%dT%H%:z";
- break;
- case 'm': // minutes
- format = "%Y-%m-%dT%H:%M%:z";
- break;
- case 's': // seconds
- format = "%Y-%m-%dT%H:%M:%S%:z";
- break;
- case 'n': // ns, nanoseconds
- format = "%Y-%m-%dT%H:%M:%S,%N%:z";
- break;
- case 'd': // date
- default:
- format = "%Y-%m-%d";
- break;
+ /* note: %:z (±ZZ:ZZ) and %N (nanoseconds) are date(1) GNU-isms absent from C libraries including glibc */
+ switch(optarg[0])
+ {
+ case 'h': // hours
+ format = "%Y-%m-%dT%H%:z";
+ break;
+ case 'm': // minutes
+ format = "%Y-%m-%dT%H:%M%:z";
+ break;
+ case 's': // seconds
+ format = "%Y-%m-%dT%H:%M:%S%:z";
+ break;
+ case 'n': // ns, nanoseconds
+ format = "%Y-%m-%dT%H:%M:%S,%N%:z";
+ break;
+ case 'd': // date
+ default:
+ format = "%Y-%m-%d";
+ break;
+ }
}
+ else
+ format = "%Y-%m-%d";
break;
case 'j':
jflag = true;