]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/upas/fs/strtotm.c
upas/fs: fix handling of numeric timezone offsets in strtotm
[plan9front.git] / sys / src / cmd / upas / fs / strtotm.c
1 #include <u.h>
2 #include <libc.h>
3
4 static char*
5 skiptext(char *q)
6 {
7         while(*q != '\0' && *q != ' ' && *q != '\t' && *q != '\r' && *q != '\n')
8                 q++;
9         return q;
10 }
11
12 static char*
13 skipwhite(char *q)
14 {
15         while(*q == ' ' || *q == '\t' || *q == '\r' || *q == '\n')
16                 q++;
17         return q;
18 }
19
20 static char* months[] = {
21         "jan", "feb", "mar", "apr",
22         "may", "jun", "jul", "aug",
23         "sep", "oct", "nov", "dec"
24 };
25
26 int
27 strtotm(char *p, Tm *t)
28 {
29         char *q, *r;
30         int j;
31         Tm tm;
32         int delta;
33
34         delta = 0;
35         memset(&tm, 0, sizeof(tm));
36         tm.mon = -1;
37         tm.hour = -1;
38         tm.min = -1;
39         tm.year = -1;
40         tm.mday = -1;
41         memcpy(tm.zone, "GMT", 3);
42         for(p = skipwhite(p); *p; p = skipwhite(q)){
43                 q = skiptext(p);
44
45                 /* look for time in hh:mm[:ss] */
46                 if(r = memchr(p, ':', q - p)){
47                         tm.hour = strtol(p, 0, 10);
48                         tm.min = strtol(r + 1, 0, 10);
49                         if(r = memchr(r + 1, ':', q - (r + 1)))
50                                 tm.sec = strtol(r + 1, 0, 10);
51                         else
52                                 tm.sec = 0;
53                         continue;
54                 }
55
56                 /* look for month */
57                 for(j = 0; j < 12; j++)
58                         if(cistrncmp(p, months[j], 3) == 0){
59                                 tm.mon = j;
60                                 break;
61                         }
62                 if(j != 12)
63                         continue;
64
65                 /* look for time zone [A-Z][A-Z]T */
66                 if(q - p == 3)
67                 if(p[0] >= 'A' && p[0] <= 'Z')
68                 if(p[1] >= 'A' && p[1] <= 'Z')
69                 if(p[2] == 'T'){
70                         strecpy(tm.zone, tm.zone + 4, p);
71                         continue;
72                 }
73
74                 if(p[0] == '+'||p[0] == '-')
75                 if(q - p == 5 && strspn(p + 1, "0123456789") == 4){
76                         delta = (((p[1] - '0')*10 + p[2] - '0')*60 + (p[3] - '0')*10 + p[4] - '0')*60;
77                         if(p[0] == '-')
78                                 delta = -delta;
79                         continue;
80                 }
81                 if(strspn(p, "0123456789") == q - p){
82                         j = strtol(p, nil, 10);
83                         if(j >= 1 && j <= 31)
84                                 tm.mday = j;
85                         if(j >= 1900)
86                                 tm.year = j - 1900;
87                         continue;
88                 }
89                 //eprint("strtotm: garbage %.*s\n", utfnlen(p, q - p), p);
90         }
91         if(tm.mon < 0 || tm.year < 0
92         || tm.hour < 0 || tm.min < 0
93         || tm.mday < 0)
94                 return -1;
95
96         *t = *localtime(tm2sec(&tm) - delta);
97         return 0;
98 }