#define _XOPEN_SOURCE #include #include #include #include #include #include const char *fmts[] = { "%R", "%T", "%d-%m", "%d-%m %H", "%d-%m %R", "%d-%m %T", "%d-%m-%Y", "%d-%m-%Y %H", "%d-%m-%Y %R", "%d-%m-%Y %T" }; time_t parse_date(char *str) { time_t local = time(NULL); struct tm *tm = localtime(&local); char flag = 0; for (size_t i = 0; i < sizeof(fmts) / sizeof(char *); i++) { char *res = strptime(str, fmts[i], tm); if (res && *res == '\0') { flag = 1; break; } } if (flag == 0) { fprintf(stderr, "date: parsing: invalid format\n"); exit(1); } time_t rt = mktime(tm); if (rt < 0) { if (rt == -1) fprintf(stderr, "date: parsing: %s\n", strerror(errno)); else fprintf(stderr, "date: parsing: invalid date\n"); exit(1); } return rt; } int main(int argc, char **argv) { time_t t = time(NULL); char *fmt = "%a %b %e %H:%M:%S %Z %Y"; /* For -s flag */ struct timespec ts; int opt; while ((opt = getopt(argc, argv, "s:d:u")) != -1) { switch (opt) { case 's': ts.tv_sec = parse_date(optarg); if (clock_settime(CLOCK_REALTIME, &ts) < 0) { fprintf(stderr, "date: settime: %s\n", strerror(errno)); return 1; } return 0; case 'd': t = parse_date(optarg); break; case 'u': if (setenv("TZ", "UTC0", 1) < 0) { fprintf(stderr, "date: %s\n", strerror(errno)); return 1; } break; default: puts("date [rsdu] [+\"fmt\"]\n\t-s TIME Set new date\n\t-d TIME Print new date\n\t-u Work in UTC\n\nRecognized TIME formats:"); for (size_t i = 0; i < sizeof(fmts) / sizeof(char *); i++) puts(fmts[i]); return 0; } } argv += optind; argc -= optind; if (argc != 0) if (argv[0][0] == '+') fmt = argv[0] + 1; struct tm *tm = localtime(&t); char buf[256]; strftime(buf, sizeof(buf), fmt, tm); puts(buf); return 0; }