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