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