/[debian]/mimetic/trunk/mimetic/rfc822/datetime.cxx
ViewVC logotype

Contents of /mimetic/trunk/mimetic/rfc822/datetime.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 511 - (show annotations)
Sun Jan 21 20:13:31 2007 UTC (14 years, 5 months ago) by gregoa
File size: 10342 byte(s)
* New upstream release.
1 /***************************************************************************
2 copyright : (C) 2002-2005 by Stefano Barbato
3 email : stefano@codesink.org
4
5 $Id: datetime.cxx,v 1.3 2007/01/21 14:55:34 tat Exp $
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16 #include <iomanip>
17 #include <sstream>
18 #include <mimetic/rfc822/datetime.h>
19 #include <mimetic/strutils.h>
20 #include <mimetic/tokenizer.h>
21 #include <mimetic/utils.h>
22
23
24 namespace mimetic
25 {
26
27
28 using namespace std;
29 using namespace mimetic;
30
31 DateTime::Zone::Zone(int iZone)
32 : m_iZone(iZone), m_iZoneIdx(0)
33 {
34 for(int i = 0; ms_offset[i] != 0; ++i)
35 if(iZone == ms_offset[i])
36 {
37 m_iZoneIdx = i;
38 }
39 }
40 DateTime::Zone::Zone(const string& txt)
41 : m_iZone(0), m_iZoneIdx(0), m_sZone(txt)
42 {
43 if(txt.empty())
44 return;
45 istring iTxt(txt.begin(), txt.end());
46 for(int i = 0; ms_label[i] != 0; ++i)
47 {
48 if(iTxt == ms_label[i])
49 {
50 m_iZone = ms_offset[i];
51 m_iZoneIdx = i;
52 }
53 }
54 if(m_iZone == 0)
55 { // check if txt is a numeric timezone (+0200)
56 string tz = txt;
57 if(tz[0] == '+' || tz[0] == '-' || (tz[0] >= '0' && tz[0] <= '9'))
58 {
59 int sign = (tz[0] == '-' ? -1 : 1);
60 tz.erase(0,1);
61 m_iZone = utils::str2int(tz) * sign;
62 }
63 }
64 }
65 bool DateTime::Zone::operator==(const string& mText)
66 {
67 istring txt(mText.begin(), mText.end());
68 return txt == ms_label[m_iZoneIdx] ||
69 utils::str2int(mText) == ms_offset[m_iZoneIdx];
70 }
71 bool DateTime::Zone::operator==(int iZone)
72 {
73 return m_iZone == iZone;
74 }
75 string DateTime::Zone::name() const
76 {
77 if(m_iZoneIdx)
78 return ms_label[m_iZoneIdx];
79 else {
80 string sTz = utils::int2str(m_iZone);
81 if(m_iZone >= 0)
82 {
83 sTz.insert(0u, 4-sTz.length(),'0'); // add zeroes
84 sTz.insert(0u, 1, '+');
85 } else {
86 sTz.insert(1, 5-sTz.length(),'0'); // add zeroes
87 }
88 return sTz;
89 }
90 }
91 short DateTime::Zone::ordinal() const
92 {
93 return m_iZone;
94 }
95
96 DateTime::Month::Month(int iMonth)
97 : m_iMonth(iMonth)
98 {
99 if(m_iMonth < 1 || m_iMonth > 12)
100 m_iMonth = 0;
101 }
102 DateTime::Month::Month(const string& txt)
103 : m_iMonth(0)
104 {
105 istring iTxt(txt.begin(), txt.end());
106 if(iTxt.length() == 3)
107 {
108 for(int i = 1; i < 13; ++i)
109 if(iTxt == ms_label[i][mnShort])
110 {
111 m_iMonth = i;
112 return;
113 }
114 } else {
115 for(int i = 1; i < 13; ++i)
116 if(iTxt == ms_label[i][mnLong])
117 {
118 m_iMonth = i;
119 return;
120 }
121 }
122 }
123 bool DateTime::Month::operator==(const string& mText) const
124 {
125 istring imText(mText.begin(), mText.end());
126 return imText == ms_label[m_iMonth][mnShort] ||
127 imText == ms_label[m_iMonth][mnLong];
128 }
129 bool DateTime::Month::operator==(int iMonth) const
130 {
131 return m_iMonth == iMonth;
132 }
133 string DateTime::Month::name(bool longName) const
134 {
135 return ms_label[m_iMonth][longName ? mnLong : mnShort];
136 }
137 short DateTime::Month::ordinal() const
138 {
139 return m_iMonth;
140 }
141
142
143 DateTime::DayOfWeek::DayOfWeek(int iDayOfWeek)
144 : m_iDayOfWeek(iDayOfWeek)
145 {
146 if(m_iDayOfWeek < 1 || m_iDayOfWeek > 7)
147 m_iDayOfWeek = 0;
148 }
149
150 DateTime::DayOfWeek::DayOfWeek(const string& txt)
151 : m_iDayOfWeek(0)
152 {
153 istring iTxt(txt.begin(), txt.end());
154 if(iTxt.length() == 3)
155 {
156 for(int i = 1; i < 8; ++i)
157 if(iTxt == ms_label[i][mnShort])
158 {
159 m_iDayOfWeek = i;
160 return;
161 }
162 } else {
163 for(int i = 1; i < 8; ++i)
164 if(iTxt == ms_label[i][mnLong])
165 {
166 m_iDayOfWeek = i;
167 return;
168 }
169 }
170 }
171 bool DateTime::DayOfWeek::operator==(const string& mText)
172 {
173 istring imText(mText.begin(), mText.end());
174 return imText == ms_label[m_iDayOfWeek][mnShort] ||
175 imText == ms_label[m_iDayOfWeek][mnLong];
176 }
177 bool DateTime::DayOfWeek::operator==(int iDayOfWeek)
178 {
179 return m_iDayOfWeek == iDayOfWeek;
180 }
181 string DateTime::DayOfWeek::name(bool longName) const
182 {
183 return ms_label[m_iDayOfWeek][longName ? mnLong : mnShort];
184 }
185 short DateTime::DayOfWeek::ordinal() const
186 {
187 return m_iDayOfWeek;
188 }
189
190 //////////////////////////////
191
192 const char *DateTime::DayOfWeek::ms_label[][2] = {
193 {"", ""},
194 {"Mon", "Monday"},
195 {"Tue", "Tuesday"},
196 {"Wed", "Wednesday"},
197 {"Thu", "Thursday"},
198 {"Fri", "Friday"},
199 {"Sat", "Saturday"},
200 {"Sun", "Sunday"},
201 {0, 0}
202 };
203
204 const char *DateTime::Month::ms_label[][2] = {
205 {"", ""},
206 {"Jan", "January"},
207 {"Feb", "February"},
208 {"Mar", "March"},
209 {"Apr", "April"},
210 {"May", "May"},
211 {"Jun", "June"},
212 {"Jul", "July"},
213 {"Aug", "August"},
214 {"Sep", "September"},
215 {"Oct", "October"},
216 {"Nov", "November"},
217 {"Dec", "December"},
218 {0, 0}
219 };
220
221 //const char *DateTime::Zone::ms_label[] = {
222 // "UT", "GMT","EST","EDT","CST", "CDT", "MST", "MDT","PST", "PDT", 0
223 //};
224
225 const char *DateTime::Zone::ms_label[] = {
226 "UNK",
227 "GMT", "UT", "BST", "CET",
228 "MET", "EET", "IST","METDST", "MET DST",
229 "EDT", "CDT", "EST", "CST",
230 "MDT", "MST", "PDT", "HKT",
231 "PST", "JST", 0
232 };
233
234 int DateTime::Zone::ms_offset[] = {
235 0,
236 +000, +000, +100, +100,
237 +100, +200, +200, +200, +200,
238 -400, -500, -500, -600,
239 -600, -700, -700, +800,
240 -800 +900,
241 0
242 };
243
244 /**
245 * Default constructor sets the Date to the Epoch (00:00:00 UTC, January 1, 1970)
246 */
247 DateTime::DateTime()
248 : m_iDayOfWeek(0), m_iDay(1), m_iMonth(1), m_iYear(1970),
249 m_iHour(0), m_iMinute(0), m_iSecond(0),
250 m_zone("UTC")
251 {
252 }
253
254 DateTime::DateTime(const string& text)
255 : m_iDayOfWeek(0), m_iDay(1), m_iMonth(1), m_iYear(1970),
256 m_iHour(0), m_iMinute(0), m_iSecond(0),
257 m_zone("UTC")
258 {
259 set(text);
260 }
261
262 DateTime::DateTime(const char* cstr)
263 : m_iDayOfWeek(0), m_iDay(1), m_iMonth(1), m_iYear(1970),
264 m_iHour(0), m_iMinute(0), m_iSecond(0),
265 m_zone("UTC")
266 {
267 set(cstr);
268 }
269
270 void DateTime::set(const string& input)
271 {
272 if(input.empty())
273 return;
274 string can_input = remove_external_blanks(canonical(input));
275 StringTokenizer stok(&can_input, " ,");
276 string tok; int i = 0;
277 if(!stok.next(tok)) return;
278 if(!tok.empty() && !isdigit(tok[0]))
279 m_iDayOfWeek = DayOfWeek(tok).ordinal();
280 else {
281 // there's no day of week
282 m_iDay = utils::str2int(tok);
283 ++i;
284 }
285
286 // gg mon aa[aa]
287 while(i < 3)
288 {
289 if(!stok.next(tok)) return;
290 if(tok.empty())
291 continue; /* there's a ' ' after ',' ("Wed, 23 Nov...") */
292 switch(i)
293 {
294 case 0: m_iDay = utils::str2int(tok); break;
295 case 1: m_iMonth = Month(tok).ordinal(); break;
296 case 2: m_iYear = utils::str2int(tok); break;
297 }
298 ++i;
299 }
300
301 stok.setDelimList(" :");
302 for(i = 0; i < 3; ++i)
303 {
304 if(!stok.next(tok)) return;
305 switch(i)
306 {
307 case 0: m_iHour = utils::str2int(tok); break;
308 case 1: m_iMinute = utils::str2int(tok); break;
309 case 2: // seconds field is optional
310 if(tok.length() == 2)
311 {
312 m_zone = "";
313 m_iSecond = utils::str2int(tok);
314 } else {
315 m_zone = tok;
316 }
317 break;
318 }
319 }
320
321 stok.setDelimList(" ");
322 // handles multi word timezones (MET DST)
323 while(stok.next(tok))
324 {
325 if(!m_zone.empty())
326 m_zone += " ";
327 m_zone += tok;
328 }
329 }
330
331
332 /*
333 based on an algorithm of J.I. Perelman [1907].
334 */
335 DateTime::DayOfWeek DateTime::dayOfWeek() const
336 {
337 if(!m_iDayOfWeek)
338 { // code from C-Faq Question 20.31
339 int y = year(), m = month().ordinal(), d = day();
340 static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
341 y -= m < 3;
342 m_iDayOfWeek = (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
343 // we use 1(Mon)..7 not 0(Sun)..6 as returned by the previous algorithm
344 // so convert
345 m_iDayOfWeek = (m_iDayOfWeek == 0 ? 7 : m_iDayOfWeek);
346 }
347 return DayOfWeek(m_iDayOfWeek);
348 }
349
350 short DateTime::day() const
351 {
352 return m_iDay;
353 }
354
355 DateTime::Month DateTime::month() const
356 {
357 return Month(m_iMonth);
358 }
359
360 short DateTime::year() const
361 {
362 return m_iYear;
363 }
364
365 short DateTime::hour() const
366 {
367 return m_iHour;
368 }
369
370 short DateTime::minute() const
371 {
372 return m_iMinute;
373 }
374
375 short DateTime::second() const
376 {
377 return m_iSecond;
378 }
379
380 DateTime::Zone DateTime::zone() const
381 {
382 return Zone(m_zone);
383 }
384
385
386 std::string DateTime::str() const
387 {
388 stringstream ss;
389 ss << *this;
390 return ss.str();
391 }
392
393 FieldValue* DateTime::clone() const
394 {
395 return new DateTime(*this);
396 }
397
398 ostream& operator<<(ostream& os, const DateTime& dt)
399 {
400 int width = os.width(), fill = os.fill();
401
402 os << dt.dayOfWeek().name() << ", "
403 << setw(2) << setfill('0') << dt.day() << " "
404 << dt.month().name() << " "
405 << setw(2) << setfill('0') << dt.year() << " "
406 << setw(2) << setfill('0') << dt.hour() << ":"
407 << setw(2) << setfill('0') << dt.minute() << ":"
408 << setw(2) << setfill('0') << dt.second() << " "
409 << dt.zone().name();
410
411 os.width(width);
412 os.fill(fill);
413 return os;
414 }
415
416
417 }
418

  ViewVC Help
Powered by ViewVC 1.1.26