1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53#define FOR_date
54#include "toys.h"
55
56GLOBALS(
57 char *r, *D, *d;
58
59 unsigned nano;
60)
61
62
63static void parse_date(char *str, time_t *t)
64{
65 char *new_tz = NULL, *old_tz, *s = str;
66
67 if (!strncmp(str, "TZ=\"", 4)) {
68
69 new_tz = str+4;
70 if (!(str = strchr(new_tz, '"'))) xvali_date(0, s);
71 *str++ = 0;
72 while (isspace(*str)) str++;
73
74
75 old_tz = getenv("TZ");
76 setenv("TZ", new_tz, 1);
77 tzset();
78 }
79 time(t);
80 xparsedate(str, t, &TT.nano, 1);
81 if (new_tz) {
82 if (old_tz) setenv("TZ", old_tz, 1);
83 else unsetenv("TZ");
84 }
85}
86
87
88static void puts_time(char *fmt, struct tm *tm)
89{
90 char *s, *snap;
91 long width = width;
92
93 for (s = fmt;;s++) {
94
95
96 if (*(snap = s) == '%') {
97 width = isdigit(*++s) ? *(s++)-'0' : 9;
98 if (*s && *s != 'N') continue;
99 } else if (*s) continue;
100
101
102 if (*s) *snap = 0;
103 if (!strftime(toybuf, sizeof(toybuf)-10, fmt, tm))
104 perror_exit("bad format '%s'", fmt);
105 if (*s) {
106 snap = toybuf+strlen(toybuf);
107 sprintf(snap, "%09u", TT.nano);
108 snap[width] = 0;
109 }
110 fputs(toybuf, stdout);
111 if (!*s || !*(fmt = s+1)) break;
112 }
113 xputc('\n');
114}
115
116void date_main(void)
117{
118 char *setdate = *toys.optargs, *format_string = "%a %b %e %H:%M:%S %Z %Y",
119 *tz = NULL;
120 time_t t;
121
122 if (FLAG(u)) {
123 tz = getenv("TZ");
124 setenv("TZ", "UTC", 1);
125 tzset();
126 }
127
128 if (TT.d) {
129 if (TT.D) {
130 struct tm tm = {};
131 char *s = strptime(TT.d, TT.D+(*TT.D=='+'), &tm);
132
133 t = (s && *s) ? xvali_date(&tm, s) : xvali_date(0, TT.d);
134 } else parse_date(TT.d, &t);
135 } else {
136 struct timespec ts;
137 struct stat st;
138
139 if (TT.r) {
140 xstat(TT.r, &st);
141 ts = st.st_mtim;
142 } else clock_gettime(CLOCK_REALTIME, &ts);
143
144 t = ts.tv_sec;
145 TT.nano = ts.tv_nsec;
146 }
147
148
149 if (!setdate);
150
151 else if (*setdate == '+') {
152 format_string = toys.optargs[0]+1;
153 setdate = toys.optargs[1];
154
155
156 } else if (setdate) {
157 struct timeval tv;
158
159 parse_date(setdate, &t);
160 tv.tv_sec = t;
161 tv.tv_usec = TT.nano/1000;
162 if (settimeofday(&tv, NULL) < 0) perror_msg("cannot set date");
163 }
164
165 puts_time(format_string, localtime(&t));
166
167 if (FLAG(u)) {
168 if (tz) setenv("TZ", tz, 1);
169 else unsetenv("TZ");
170 tzset();
171 }
172
173 return;
174}
175