openMSX
Date.cc
Go to the documentation of this file.
1 #include "Date.hh"
2 #include <sstream>
3 #include <iomanip>
4 #include <cstdio>
5 #include <cstring>
6 
7 namespace openmsx {
8 
9 namespace Date {
10 
11 const char* const days[7] = {
12  "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ,"Sun"
13 };
14 
15 const char* const months[12] = {
16  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
17  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
18 };
19 
20 template<bool FIRST, unsigned MUL, typename T>
21 static inline bool parseDigit(unsigned c, T& t)
22 {
23  c -= '0';
24  if (c > 9) return false;
25  if (FIRST) {
26  t = c * MUL;
27  } else {
28  t += c * MUL;
29  }
30  return true;
31 }
32 
33 time_t fromString(const char* p)
34 {
35  struct tm tm;
36 
37  // skip day
38  p += 3;
39 
40  // space
41  if (*p++ != ' ') return time_t(-1);
42 
43  // Parse month
44  switch (*p++) {
45  case 'J': // Jan Jun Jul
46  switch (*p++) {
47  case 'a': // Jan
48  if (*p++ != 'n') return time_t(-1);
49  tm.tm_mon = 0; break;
50  case 'u': // Jun Jul
51  switch (*p++) {
52  case 'n': tm.tm_mon = 5; break;
53  case 'l': tm.tm_mon = 6; break;
54  default: return time_t(-1);
55  }
56  break;
57  default: return time_t(-1);
58  }
59  break;
60  case 'F': // Feb
61  if (*p++ != 'e') return time_t(-1);
62  if (*p++ != 'b') return time_t(-1);
63  tm.tm_mon = 1;
64  break;
65  case 'M': // Mar May
66  if (*p++ != 'a') return time_t(-1);
67  switch (*p++) {
68  case 'r': tm.tm_mon = 2; break;
69  case 'y': tm.tm_mon = 4; break;
70  default: return time_t(-1);
71  }
72  break;
73  case 'A': // Apr Aug
74  switch (*p++) {
75  case 'p': // Apr
76  if (*p++ != 'r') return time_t(-1);
77  tm.tm_mon = 3; break;
78  case 'u': // Aug
79  if (*p++ != 'g') return time_t(-1);
80  tm.tm_mon = 7; break;
81  default: return time_t(-1);
82  }
83  break;
84  case 'S': // Sep
85  if (*p++ != 'e') return time_t(-1);
86  if (*p++ != 'p') return time_t(-1);
87  tm.tm_mon = 8;
88  break;
89  case 'O': // Oct
90  if (*p++ != 'c') return time_t(-1);
91  if (*p++ != 't') return time_t(-1);
92  tm.tm_mon = 9;
93  break;
94  case 'N': // Nov
95  if (*p++ != 'o') return time_t(-1);
96  if (*p++ != 'v') return time_t(-1);
97  tm.tm_mon = 10;
98  break;
99  case 'D': // Dec
100  if (*p++ != 'e') return time_t(-1);
101  if (*p++ != 'c') return time_t(-1);
102  tm.tm_mon = 11;
103  break;
104  default: return time_t(-1);
105  }
106 
107  // space
108  if (*p++ != ' ') return time_t(-1);
109 
110  // parse mday
111  if (!parseDigit<true, 10>(*p++, tm.tm_mday)) return time_t(-1);
112  if (!parseDigit<false, 1>(*p++, tm.tm_mday)) return time_t(-1);
113  if ((tm.tm_mday < 1) || (31 < tm.tm_mday) ) return time_t(-1);
114 
115  // space
116  if (*p++ != ' ') return time_t(-1);
117 
118  // parse hour
119  if (!parseDigit<true, 10>(*p++, tm.tm_hour)) return time_t(-1);
120  if (!parseDigit<false, 1>(*p++, tm.tm_hour)) return time_t(-1);
121  if ((tm.tm_hour < 0) || (23 < tm.tm_hour)) return time_t(-1);
122 
123  // colon
124  if (*p++ != ':') return time_t(-1);
125 
126  // parse minute
127  if (!parseDigit<true, 10>(*p++, tm.tm_min)) return time_t(-1);
128  if (!parseDigit<false, 1>(*p++, tm.tm_min)) return time_t(-1);
129  if ((tm.tm_min < 0) || (59 < tm.tm_min)) return time_t(-1);
130 
131  // colon
132  if (*p++ != ':') return time_t(-1);
133 
134  // parse second
135  if (!parseDigit<true, 10>(*p++, tm.tm_sec)) return time_t(-1);
136  if (!parseDigit<false, 1>(*p++, tm.tm_sec)) return time_t(-1);
137  if ((tm.tm_sec < 0) || (59 < tm.tm_sec)) return time_t(-1);
138 
139  // space
140  if (*p++ != ' ') return time_t(-1);
141 
142  // parse year
143  if (!parseDigit<true, 1000>(*p++, tm.tm_year)) return time_t(-1);
144  if (!parseDigit<false, 100>(*p++, tm.tm_year)) return time_t(-1);
145  if (!parseDigit<false, 10>(*p++, tm.tm_year)) return time_t(-1);
146  if (!parseDigit<false, 1>(*p++, tm.tm_year)) return time_t(-1);
147  tm.tm_year -= 1900;
148  if (tm.tm_year < 0) return time_t(-1);
149 
150  tm.tm_isdst = -1;
151  return mktime(&tm);
152 }
153 
154 std::string toString(time_t time)
155 {
156  if (time < 0) time = 0;
157  struct tm* tm;
158  tm = localtime(&time);
159  std::ostringstream sstr;
160  sstr << std::setfill('0')
161  << days [tm->tm_wday] << ' '
162  << months[tm->tm_mon] << ' '
163  << std::setw(2) << tm->tm_mday << ' '
164  << std::setw(2) << tm->tm_hour << ':'
165  << std::setw(2) << tm->tm_min << ':'
166  << std::setw(2) << tm->tm_sec << ' '
167  << std::setw(4) << (tm->tm_year + 1900);
168  return sstr.str();
169 }
170 
171 } // namespace Date
172 
173 } // namespace openmsx