1 #define _GNU_SOURCE
2 #define __deprecated__
3 #include "scan.h"
4 #include "byte.h"
5 #include "case.h"
6 #include <time.h>
7 #include <stdlib.h>
8 
9 #ifdef sgi
10 extern char** environ;
11 #endif
12 
13 /* "2014-05-27T19:22:16Z" */
scan_iso8601(const char * in,struct timespec * t)14 size_t scan_iso8601(const char* in,struct timespec* t) {
15   struct tm x;
16   const char* c;
17   unsigned long tmp;
18   size_t i;
19   if (!(c=in)) return 0;
20   if ((i=scan_ulong(c,&tmp))<4 || c[i]!='-') return 0;
21                                                        c+=i+1; x.tm_year=(int)(tmp-1900);
22   if (scan_ulong(c,&tmp)!=2 || c[2]!='-') return 0;
23                                                     c+=3; x.tm_mon=(int)(tmp-1);
24   if (scan_ulong(c,&tmp)!=2 || c[2]!='T') return 0;
25                                                     c+=3; x.tm_mday=(int)tmp;
26   if (scan_ulong(c,&tmp)!=2 || c[2]!=':') return 0;
27                                                     c+=3; x.tm_hour=(int)tmp;
28   if (scan_ulong(c,&tmp)!=2 || c[2]!=':') return 0;
29                                                     c+=3; x.tm_min=(int)tmp;
30   if (scan_ulong(c,&tmp)!=2) return 0;
31                                        c+=2; x.tm_sec=(int)tmp;
32   if (*c=='.') {
33     ++c;
34     i=scan_ulong(c,&tmp);
35     c+=i;
36     if (i<1 || i>9)
37       t->tv_nsec=0;
38     else {
39       while (i<9) {
40 	++i;
41 	tmp*=10;
42       }
43       t->tv_nsec=tmp;
44     }
45   }
46 
47 #ifdef __MINGW32__
48   x.tm_wday=x.tm_yday=x.tm_isdst=0;
49 #else
50   x.tm_wday=x.tm_yday=x.tm_isdst=x.tm_gmtoff=0;
51 #endif
52 #if defined(__dietlibc__) || defined(__GLIBC__)
53   t->tv_sec=timegm(&x);
54 #elif defined(__MINGW32__)
55   t->tv_sec=mktime(&x);
56 #else
57   {
58 #ifdef sgi
59     char** old=environ;
60     char** newenv={0};
61     environ=newenv;
62     t->tv_sec=mktime(&x);
63     environ=old;
64 #else
65     char* old=getenv("TZ");
66     unsetenv("TZ");
67     t->tv_sec=mktime(&x);
68     if (old) setenv("TZ",old,1);
69 #endif
70   }
71 #endif
72 
73   if (*c=='+' || *c=='-') {
74     int signum = (*c=='-') - (*c=='+');
75     ++c;
76     if (scan_ulong(c,&tmp)!=4) return 0;
77     c+=4;
78     t->tv_sec+=signum*60*(int)(tmp/100)*60+(int)(tmp%100);
79   } else if (*c=='Z')
80     ++c;
81   else
82     return 0;
83   return (size_t)(c-in);
84 }
85