1 //
2 // HtDateTime.h
3 //
4 // HtDateTime: Parse, split, compare and format dates and times.
5 // Uses locale.
6 //
7 // Part of the ht://Dig package <http://www.htdig.org/>
8 // Copyright (c) 1999-2004 The ht://Dig Group
9 // For copyright details, see the file COPYING in your distribution
10 // or the GNU Library General Public License (LGPL) version 2 or later
11 // <http://www.gnu.org/copyleft/lgpl.html>
12 //
13 // $Id: HtDateTime.h,v 1.19 2004/05/28 13:15:20 lha Exp $
14
15 ///////
16 // Class for Date and Time
17 // Gabriele Bartolini - Prato - Italia
18 // Started: 22.04.1999
19 ///////
20
21 // Version: 1.0
22 // Release date: 07.05.1999
23
24 //
25 // General purpose of HtDateTime
26 // The general purpose of this class, is to provide an interface for
27 // date and time managing, and to unload the programmer to manage
28 // time_t, struct tm, time system functions and other related procedures
29 // locally ... Everything regarding time and date must be put here.
30 // D'you agree with me? Well, here is a summary of the class capabilities.
31
32 // Attributes of the class:
33 //
34 // HtDateTime class has only 2 member attributes
35 // - time_t Ht_t
36 // - bool local_time
37 //
38 // Obviously Ht_t contains the most important piece of information.
39 // local_time assumes a true value if we wanna consider the date and
40 // time information as local. False means that our object value is
41 // referred to the Greenwich Meridian time.
42
43 // Interface provided:
44 //
45 // Construction:
46 // - Default: set the date time value to now
47 // - By passing a time_t value or pointer: Set to it
48 // - By passing a struct tm value or pointer: Set to it
49 // The last one could be useful sometimes. But it had better not to
50 // be used.
51 //
52 // Parsing interface:
53 // Not yet implemented ... :-)
54 //
55 // Setting Interface:
56 // - from time_t: copy the time_t value into the object
57 // - from struct tm: set the object's time_t value by converting
58 // the value from the struct tm. If local_time is set to true,
59 // converts it with mktime, else uses HtTimeGM.
60 // - set to now
61 // - from a string, by passing the input format: the method uses
62 // strptime syntax (and invokes Htstrptime). For now, timezone
63 // is ignored, and so data are stored as a GM date time value.
64 // - from an int series, by specifying all the information (year,
65 // month, day, hour, minute and second). It's all stored as
66 // GM value.
67 // - from various standard formats, such as C asctime, RFC 1123,
68 // RFC 850 (these 3 types are suggested by the HTTP/1.1 standard),
69 // ISO 8601, date and time default representation for the locale.
70 // This list could get longer ... It all depends on us.
71 // - setting the date and time to be represented in a local value
72 // or universal (GM) one.
73 //
74 // Getting Interface
75 // - in a personalized output format, by passing a string with
76 // strftime values.
77 // - in various standard formats, like C asctime, RFC 1123,
78 // RFC 850, ISO 8601 (short too), date and time default
79 // representation for the locale.
80 // - getting the time_t value
81 // - queries the local time status
82 // - getting specific piece of information of both the date and the
83 // the time, like the year, the month, the day of the week, of
84 // the year or of the month, ... In short, every kind of thing
85 // a tm structure is able to store ...
86 //
87 // Operator overloading
88 // - Copy
89 // - Every kind of logical comparison between 2 objects
90 //
91 // Comparison interface
92 // This is divided in 2 sections.
93 // - Static section:
94 // comparison are made on a 2 struct tm values basis.
95 // It's possible to compare the whole date time value, or
96 // simply the date or the time value.
97 // - Member functions section:
98 // comparison are made between 2 HtDateTime objects.
99 // You can compare either the whole date time, or the date, or the
100 // time, both as they are or referring their values to the GM value.
101 //
102 // System functions interface
103 // They are all done with previous "configure" checks
104 // - for strptime
105 // - for timegm
106 //
107 // Static methods
108 // - check for a leap year
109 // - check for a valid year number (according with time_t capabilities)
110 // - check for a valid month number
111 // - check for a valid day
112 // - converts a 2 digits year number into a 4 digits one: from 1970 to 2069.
113 // - converts a 4 digits year number into a 2 digits one.
114 // - retrieve the difference in seconds between 2 HtDateTime objs
115 //
116 // Test Interface (only by defining TEST_HTDATETIME directive).
117 //
118
119
120 #ifndef _HTDATETIME_H
121 #define _HTDATETIME_H
122
123 #ifdef HAVE_CONFIG_H
124 # include "htconfig.h"
125 #endif
126
127 #if TIME_WITH_SYS_TIME
128 #include <sys/time.h>
129 #include <time.h>
130 #else
131 # if HAVE_SYS_TIME_H
132 # include <sys/time.h>
133 # else
134 # include <time.h>
135 # endif
136 #endif
137
138 #include "htString.h"
139
140 // If you wanna do some tests
141 #define TEST_HTDATETIME
142
143
144 class HtDateTime
145 {
146 public:
147
148 ///////
149 // Construction
150 ///////
151
152 // Default: now and local
HtDateTime()153 HtDateTime() {SettoNow(); ToLocalTime();}
154
155 // From an integer (seconds from epoc)
156 // Causes ambiguity in systems with time_t an integer...
157 // HtDateTime(const int i) {SetDateTime((time_t)i); ToLocalTime();}
158
159 // From a time_t value and pointer
HtDateTime(time_t & t)160 HtDateTime(time_t &t) {SetDateTime(t); ToLocalTime();}
HtDateTime(time_t * t)161 HtDateTime(time_t *t) {SetDateTime(t); ToLocalTime();}
162
163 // From a struct tm value and pointer
HtDateTime(struct tm & t)164 HtDateTime(struct tm &t) {SetDateTime(t); ToLocalTime();}
HtDateTime(struct tm * t)165 HtDateTime(struct tm *t) {SetDateTime(t); ToLocalTime();}
166
167 // Copy constructor
168 inline HtDateTime(const HtDateTime& rhs);
169
170 ///////
171 // Interface methods
172 ///////
173
174 ///////
175 // "Parsing" interface
176 ///////
177
178 int Parse(const char *); // It looks for the similar format
179 // then sets the date by invoking
180 // right method
181
182
183 ///////
184 // "Setting" interface
185 ///////
186
187 // Setting from a time_t value
SetDateTime(const time_t & t)188 void SetDateTime(const time_t &t) { Ht_t = t; } // by reference
SetDateTime(const time_t * t)189 void SetDateTime(const time_t *t) { Ht_t = *t; } // by pointer
190
191 // Set object time_t value from a struct tm
192 void SetDateTime(struct tm *); // by pointer
SetDateTime(struct tm & t)193 inline void SetDateTime(struct tm &t) { SetDateTime(&t);} // by reference
194
195 // Set GM Time from single values input
196 // Return true if it all went good, false else
197 bool SetGMDateTime( int year, int mon, int mday,
198 int hour=0, int min=0, int sec=0);
199
200 // Set to Now
201 void SettoNow();
202
203 // Parsing various input string format
204 // It ignores time Zone value - always stores as GM
205 char *SetFTime(const char *, const char *); // as strptime
206
207 void SetAscTime(char *); // Sun Nov 6 08:49:37 1994
208 void SetRFC1123(char *); // Sun, 06 Nov 1994 08:49:37 GMT
209 void SetRFC850(char *); // Sunday, 06-Nov-94 08:49:37 GMT
210 void SetISO8601(char *); // 1994-11-06 08:49:37 GMT
211 void SetTimeStamp(char *); // 19941106084937
212
213 void SetDateTimeDefault(char *); // Default date and time representation
214 // for the locale
215
216 ///////
217 // Methods for setting Local and GM time formats (Switches)
218 ///////
219
ToLocalTime()220 void ToLocalTime() {local_time=true;}
ToGMTime()221 void ToGMTime() {local_time=false;}
222
223
224 ///////
225 // "Getting" interface
226 ///////
227
228
229 ///////
230 // Output formats
231 ///////
232
233 // Personalized output
234 char *GetFTime(const char *format) const; // as strftime
235 size_t GetFTime(char *, size_t, const char *) const; // as strftime
236
237 char *GetAscTime() const; // Sun Nov 6 08:49:37 1994
238 char *GetRFC1123() const; // Sun, 06 Nov 1994 08:49:37 GMT
239 char *GetRFC850() const; // Sunday, 06-Nov-94 08:49:37 GMT
240 char *GetISO8601() const; // 1994-11-06 08:49:37 GMT
241 char *GetTimeStamp() const; // 19941106084937
242
243 char *GetDateTimeDefault() const; // Default date and time representation
244 // for the locale
245
246 // Partial (only date or only time)
247 char *GetShortISO8601() const; // 1994-11-06
248 char *GetDateDefault() const; // Default date form for the locale
249 char *GetTimeDefault() const; // Default time form for the locale
250
251
252 ///////
253 // Gets the time_t value
254 ///////
255
GetTime_t()256 time_t GetTime_t() const {return Ht_t;}
257
258
259 ///////
260 // Gets specific date and time values (from a struct tm)
261 ///////
262
263 // Gets the year
GetYear()264 int GetYear() const { return ( GetStructTM().tm_year + 1900) ;}
265
266 // Gets the month
GetMonth()267 int GetMonth() const { return (GetStructTM().tm_mon + 1);}
268
269 // Gets the day of the week (since Sunday)
GetWDay()270 int GetWDay() const { return (GetStructTM().tm_wday + 1);}
271
272 // Gets the day of the month
GetMDay()273 int GetMDay() const { return GetStructTM().tm_mday;}
274
275 // Gets the day since january 1
GetYDay()276 int GetYDay() const { return (GetStructTM().tm_yday + 1);}
277
278 // Gets the hour
GetHour()279 int GetHour() const { return GetStructTM().tm_hour;}
280
281 // Gets the minute
GetMinute()282 int GetMinute() const { return GetStructTM().tm_min;}
283
284 // Gets the second
GetSecond()285 int GetSecond() const { return GetStructTM().tm_sec;}
286
287 // Daylight saving time is in effect at that time?
GetIsDst()288 int GetIsDst() const { return GetStructTM().tm_isdst;}
289
290
291 ///////
292 // Methods for querying localtime status
293 ///////
294
isLocalTime()295 bool isLocalTime() const {return local_time;}
isGMTime()296 bool isGMTime() const {return !local_time;}
297
298
299
300 ///////
301 // Methods for comparison
302 ///////
303
304 // Returns 0 if equal, -1 if tm1 is lower than tm2, 1 if tm1 is greater than tm2
305
306 int DateTimeCompare (const HtDateTime &) const; // Compares both date and time
307
308 int DateCompare (const HtDateTime &) const; // Compares the date
309 int TimeCompare (const HtDateTime &) const; // Compares the time
310
311 // Refers the date and the time to a GM value, then compares
312 int GMDateTimeCompare (const HtDateTime &) const; // Compares both date and time
313 int GMDateCompare (const HtDateTime &) const; // Compares the date
314 int GMTimeCompare (const HtDateTime &) const; // Compares the time
315
316
317 ///////
318 // Operator overloading
319 ///////
320
321 // For comparisons - between objects of the same class
322
323 inline bool operator==(const HtDateTime &right) const;
324 inline bool operator<(const HtDateTime &right) const;
325
326 bool operator!=(const HtDateTime &right) const
327 {return !( *this == right );}
328
329 bool operator>=(const HtDateTime &right) const
330 {return !( *this < right);}
331
332 bool operator<=(const HtDateTime &right) const
333 {return !( right < *this);}
334
335 bool operator>(const HtDateTime &right) const
336 {return right < *this; }
337
338
339 // For comparisons - between HtDateTime objects and int
340
341 bool operator==(const int right) const // with an int
342 {return ( Ht_t == (time_t) right );}
343
344 bool operator<(const int right) const // with an int
345 {return ( Ht_t < (time_t) right );}
346
347 bool operator!=(const int right) const // with an int
348 {return !( *this == right );}
349
350 bool operator>=(const int right) const // with an int
351 {return !( *this < right);}
352
353 bool operator<=(const int right) const // with an int
354 {return !( *this > right);}
355
356 bool operator>(const int right) const // with an int
357 {return (Ht_t > (time_t) right); }
358
359
360 // For Copy
361
362 inline HtDateTime &operator=(const HtDateTime &right);
363 inline HtDateTime &operator=(const int right);
364
365
366
367
368 /////// // STATIC METHODS // ///////
369
370 // Here we can add static methods as we want more :-)
371 // Then invoke them with HtDateTime::MethodXXX ()
372
373
374 inline static bool LeapYear(int); // Is a leap year?
375
376 // These checks are made for time_t compatibility
377 inline static bool isAValidYear(int); // Is a valid year number
378
379 inline static bool isAValidMonth(int); // Is a valid month number
380 inline static bool isAValidDay(int, int, int); // Is a valid day
381
382
383 // Converts a 2 digits year in a 4 one - with no checks
Year_From2To4digits(int y)384 static int Year_From2To4digits (int y)
385 {
386 if ( y >= 70 ) return y+1900;
387 else return y+2000;
388 }
389
390 // Converts a 4 digits year in a 2 one - with no checks
Year_From4To2digits(int y)391 static int Year_From4To2digits (int y)
392 {
393 if ( y >= 2000 ) return y - 2000;
394 else return y - 1900;
395 }
396
397 static int GetDiff(const HtDateTime &, const HtDateTime &);
398
399 // Check equality from 2 struct tm pointers
400 // Returns 0 if equal, -1 if tm1 is lower than tm2, 1 if tm1 is greater than tm2
401
402 // Compares the whole time information (both date and time)
403 static int DateTimeCompare(const struct tm *tm1,
404 const struct tm *tm2);
405
406 // Compares only date
407 static int DateCompare(const struct tm *tm1,
408 const struct tm *tm2);
409
410 // Compares only time
411 static int TimeCompare(const struct tm *tm1,
412 const struct tm *tm2);
413
414
415
416 /////// // HIDDEN ATTRIBUTES & METHODS // ///////
417
418 protected: // to permit inheritance
419
420 time_t Ht_t;
421 bool local_time;
422
423 static const int days[];
424
425 ///////
426 // Sets and gets the struct tm depending on local_time status
427 ///////
428
429 void RefreshStructTM() const; // Refresh its content
430 struct tm &GetStructTM() const; // gets it
GetStructTM(struct tm & t)431 void GetStructTM(struct tm & t) const { t=GetStructTM(); } // Gets and copy
432
433
434 ///////
435 // Gets the struct tm ignoring local_time status
436 ///////
437
438 struct tm &GetGMStructTM() const; // gets it
439 void GetGMStructTM(struct tm &) const; // Gets and copy
440
441
442 ///////
443 // Interface for system functions
444 ///////
445
446 // Interface for timegm
447 static time_t HtTimeGM (struct tm*);
448
449
450 #ifdef TEST_HTDATETIME
451
452 ///////
453 // Only for debug: view of struct tm fields
454 ///////
455
456 public:
457
458 static void ViewStructTM(struct tm *); // view of struct tm fields
459 virtual void ViewStructTM(); // view of struct tm fields
460 void ViewFormats(); // View of various formats
461
462 void ComparisonTest (const HtDateTime &) const; // comparison
463
464
465 // Test of the class
466 static int Test(void);
467 static int Test(char **test_dates, const char *format);
468
469 #endif
470
471 };
472
473
474 ///////
475 // Copy constructor
476 ///////
477
478 inline
HtDateTime(const HtDateTime & rhs)479 HtDateTime::HtDateTime (const HtDateTime& rhs)
480 {
481 // Copy the contents
482 Ht_t = rhs.Ht_t;
483 local_time = rhs.local_time;
484 }
485
486 ///////
487 // Operator overloading
488 ///////
489
490 inline
491 bool HtDateTime::operator==(const HtDateTime &right) const
492 {
493 if(Ht_t==right.Ht_t)
494 return true;
495 else
496 return false;
497 }
498
499 inline
500 bool HtDateTime::operator<(const HtDateTime &right) const
501 {
502 if(Ht_t < right.Ht_t) return true;
503 else return false;
504 }
505
506 ///////
507 // Copy
508 ///////
509
510 inline
511 HtDateTime &HtDateTime::operator=(const HtDateTime &right)
512 {
513 if (this != &right)
514 {
515 Ht_t=right.Ht_t; // Copy the time_t value
516 local_time=right.local_time; // Copy the local_time flag
517 }
518
519 return *this;
520 }
521
522 inline
523 HtDateTime &HtDateTime::operator=(const int right)
524 {
525 Ht_t=(time_t)right; // Copy the int as a time_t value
526 ToLocalTime();
527 return *this;
528 }
529
530
531
532
533 #endif
534