date.c (1858B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <ctype.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <time.h> 7 8 #include "util.h" 9 10 static void 11 usage(void) 12 { 13 eprintf("usage: %s [-u] [-d time] [+format | mmddHHMM[[CC]yy]]\n", argv0); 14 } 15 16 static int 17 datefield(const char *s, size_t i) 18 { 19 if (!isdigit(s[i]) || !isdigit(s[i+1])) 20 eprintf("invalid date format: %s\n", s); 21 22 return (s[i] - '0') * 10 + (s[i+1] - '0'); 23 } 24 25 static void 26 setdate(const char *s, struct tm *now) 27 { 28 struct tm date; 29 struct timespec ts; 30 31 switch (strlen(s)) { 32 case 8: 33 date.tm_year = now->tm_year; 34 break; 35 case 10: 36 date.tm_year = datefield(s, 8); 37 if (date.tm_year < 69) 38 date.tm_year += 100; 39 break; 40 case 12: 41 date.tm_year = ((datefield(s, 8) - 19) * 100) + datefield(s, 10); 42 break; 43 default: 44 eprintf("invalid date format: %s\n", s); 45 break; 46 } 47 48 date.tm_mon = datefield(s, 0) - 1; 49 date.tm_mday = datefield(s, 2); 50 date.tm_hour = datefield(s, 4); 51 date.tm_min = datefield(s, 6); 52 date.tm_sec = 0; 53 date.tm_isdst = -1; 54 55 ts.tv_sec = mktime(&date); 56 if (ts.tv_sec == -1) 57 eprintf("mktime:"); 58 ts.tv_nsec = 0; 59 60 if (clock_settime(CLOCK_REALTIME, &ts) == -1) 61 eprintf("clock_settime:"); 62 } 63 64 int 65 main(int argc, char *argv[]) 66 { 67 struct tm *now; 68 time_t t; 69 char buf[BUFSIZ], *fmt = "%a %b %e %H:%M:%S %Z %Y"; 70 71 t = time(NULL); 72 if (t == -1) 73 eprintf("time:"); 74 75 ARGBEGIN { 76 case 'd': 77 t = estrtonum(EARGF(usage()), 0, LLONG_MAX); 78 break; 79 case 'u': 80 if (setenv("TZ", "UTC0", 1) < 0) 81 eprintf("setenv:"); 82 break; 83 default: 84 usage(); 85 } ARGEND 86 87 if (!(now = localtime(&t))) 88 eprintf("localtime:"); 89 if (argc) { 90 if (argc != 1) 91 usage(); 92 if (argv[0][0] != '+') { 93 setdate(argv[0], now); 94 return 0; 95 } 96 fmt = &argv[0][1]; 97 } 98 99 strftime(buf, sizeof(buf), fmt, now); 100 puts(buf); 101 102 return fshut(stdout, "<stdout>"); 103 }