date.c (2987B)
- // utils-std: Collection of commonly available Unix tools
- // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #define _XOPEN_SOURCE 700 // strptime is in XSI
- #include "../lib/iso_parse.h" /* iso_parse */
- #include <errno.h> /* errno */
- #include <locale.h> /* setlocale */
- #include <locale.h> /* setlocale() */
- #include <stdio.h> /* BUFSIZ, perror(), puts() */
- #include <stdlib.h> /* exit(), strtol() */
- #include <time.h> /* time, localtime, tm, strftime, strptime */
- #include <unistd.h> /* getopt(), optarg, optind */
- static void
- usage()
- {
- fprintf(stderr, "date [-uR] [-d datetime] [+format]\n");
- fprintf(stderr, "date [-uR] -f now_format now [+format]\n");
- }
- int
- main(int argc, char *argv[])
- {
- char outstr[BUFSIZ];
- struct tm *tm;
- time_t now;
- char *format = "%c";
- char *input_format = NULL;
- int uflag = 0;
- int dflag = 0;
- int c;
- setlocale(LC_ALL, "");
- now = time(NULL);
- if(now == (time_t)-1)
- {
- perror("date: time");
- exit(EXIT_FAILURE);
- }
- while((c = getopt(argc, argv, ":d:f:uR")) != -1)
- {
- char *errstr = NULL;
- switch(c)
- {
- case 'd': /* Custom datetime */
- if(input_format != NULL)
- {
- fprintf(stderr, "date: Cannot both use '-d' and '-f'\n");
- exit(EXIT_FAILURE);
- }
- now = iso_parse(optarg, &errstr).tv_sec;
- dflag = 1;
- if(errstr != NULL)
- {
- fprintf(stderr, "date: iso_parse(\"%s\", …): %s\n", optarg, errstr);
- exit(EXIT_FAILURE);
- }
- break;
- case 'f': /* input datetime format */
- if(dflag == 1)
- {
- fprintf(stderr, "date: Cannot both use '-d' and '-f'\n");
- exit(EXIT_FAILURE);
- }
- input_format = optarg;
- break;
- case 'u': /* UTC timezone */
- uflag++;
- break;
- case 'R': /* Email (RFC 5322) format */
- format = "%a, %d %b %Y %H:%M:%S %z";
- break;
- case ':':
- fprintf(stderr, "date: Error: Missing operand for option: '-%c'\n", optopt);
- usage();
- return 1;
- case '?':
- fprintf(stderr, "date: Error: Unrecognised option: '-%c'\n", optopt);
- usage();
- return 1;
- }
- }
- if(uflag)
- {
- tm = gmtime(&now);
- if(tm == NULL)
- {
- perror("date: gmtime");
- exit(EXIT_FAILURE);
- }
- }
- else
- {
- tm = localtime(&now);
- if(tm == NULL)
- {
- perror("date: localtime");
- exit(EXIT_FAILURE);
- }
- }
- argc -= optind;
- argv += optind;
- if(argc > 0 && input_format != NULL)
- {
- char *res = strptime(argv[0], input_format, tm);
- if(res == NULL)
- {
- fprintf(stderr,
- "date: strptime(\"%s\", \"%s\", …) as passed by '-f' option failed\n",
- argv[0],
- input_format);
- exit(EXIT_FAILURE);
- }
- argv++;
- argc--;
- }
- if(argc > 0 && *argv && **argv == '+')
- {
- format = *argv + 1;
- argv++;
- argc--;
- }
- errno = 0;
- if(strftime(outstr, sizeof(outstr), format, tm) == 0 && errno != 0)
- {
- perror("date: strftime");
- exit(EXIT_FAILURE);
- }
- if(puts(outstr) < 0)
- {
- perror("date: puts");
- exit(EXIT_FAILURE);
- }
- return 0;
- }