home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / classsrc.pak / TIME.CPP < prev    next >
C/C++ Source or Header  |  1997-07-23  |  8KB  |  276 lines

  1. /*------------------------------------------------------------------------*/
  2. /*                                                                        */
  3. /*  TIME.CPP                                                              */
  4. /*                                                                        */
  5. /*  Copyright (c) 1993, 1994 Borland International                        */
  6. /*  All Rights Reserved                                                   */
  7. /*                                                                        */
  8. /*------------------------------------------------------------------------*/
  9.  
  10. #if !defined( __TIME_H )
  11. #include <time.h>
  12. #endif
  13.  
  14. #if !defined( __STDIO_H )
  15. #include <stdio.h>
  16. #endif
  17.  
  18. #if !defined( __CHECKS_H )
  19. #include <checks.h>
  20. #endif
  21.  
  22. #if !defined( CLASSLIB_TIME_H )
  23. #include <classlib/time.h>
  24. #endif
  25.  
  26. enum TimeZone { CarolineIslands=-11,    MarianaIslands,         Japan, 
  27.                 China,                  minusSeven,             minusSix, 
  28.                 Pakistan,               CaspianSea,             Turkey, 
  29.                 Finland,                Europe,                 Greenwich, 
  30.                 Azores,                 two,                    Greenland, 
  31.                 Atlantic,               USEastern,              USCentral, 
  32.                 USMountain,             USPacific,              Alaska, 
  33.                 Hawaii,                 Bearing};
  34.  
  35. static const unsigned long SECONDS_IN_DAY  = 86400L;
  36. static const unsigned long SECONDS_IN_HOUR = 3600L;
  37. static const unsigned      SECONDS_IN_MIN  = 60;
  38.  
  39. //  Be sure that you have set your environment variable TZ.
  40. //  For example, for Pacific coast time, set TZ=PDT8PST.  
  41. //  For other time zones, see your manuals.
  42.  
  43. struct TInitTime
  44. {
  45.     TInitTime()
  46.         { tzset(); }
  47. };
  48.  
  49. static TInitTime cludgeTime;      // To force the call to tzset()
  50.  
  51.  
  52. const TDate TTime::RefDate( (DayTy)0, (YearTy)0 );
  53. const TDate TTime::MaxDate( (DayTy)49709L, (YearTy)0 ); // ((2**32)-1)/SECONDS_IN_DAY -1
  54. static const int SUNDAY = 7;
  55.  
  56. int TTime::AssertDate( const TDate _BIDSFAR & date )
  57. {
  58.     return date.Between(RefDate,MaxDate);
  59. }   
  60.  
  61. /******************* private member functions ***********************/
  62.  
  63.  
  64. // Adjust for local time zone and Daylight Savings Time.
  65. ClockTy TTime::LocalSecs() const
  66. {
  67.     TTime local_time( Sec - timezone );
  68.     if (local_time.IsDST())
  69.         local_time.Sec += SECONDS_IN_HOUR;
  70.     return local_time.Sec;
  71. }
  72.  
  73. /*
  74.  * Builds the time from a local time, adjusting to GMT.  Does *not* adjust for DST.
  75.  */
  76. TTime TTime::BuildLocal( const TDate _BIDSFAR & date, HourTy h )
  77. {
  78.     return TTime( SECONDS_IN_DAY * (date-RefDate) + 
  79.                   SECONDS_IN_HOUR * h + 
  80.                   timezone);
  81. }
  82.  
  83. /*************** public static member functions *******************/
  84.  
  85. /*
  86.  * Return the time at which DST starts for the given year.
  87.  * Note that the time returned is the time at which DST starts locally,
  88.  * but it is returned in GMT.
  89.  */
  90. TTime TTime::BeginDST( unsigned year )
  91. {
  92.     if( year > 1986 ) 
  93.         {
  94.         TDate endMarch(31, 3, year);
  95.         return BuildLocal( endMarch.Previous(SUNDAY)+7, 2 );
  96.         }
  97.  
  98.     // Ah, remember those energy conscious years...???
  99.     if( year==1974 )
  100.         return BuildLocal( TDate(6,1,1974), 2 );
  101.     if( year==1975 )
  102.         return BuildLocal( TDate(23,2,1975), 2 );
  103.  
  104.     TDate endApril( 30, 4, year );
  105.     return BuildLocal( endApril.Previous(SUNDAY), 2 );
  106. }
  107.  
  108.  
  109. /*
  110.  * Return the time at which DST ends for the given year.
  111.  * Note that the time returned is the time at which DST ends locally,
  112.  * but it is returned in GMT.
  113.  */
  114. TTime TTime::EndDST( unsigned year )
  115. {
  116.     TDate endOctober( 31, 10, year );
  117.     return BuildLocal( endOctober.Previous(SUNDAY), 1 );
  118. }
  119.  
  120.  
  121. /************************* constructor *********************************/
  122.  
  123. // Construct TTime with current time (seconds since Jan 1, 1901).
  124. TTime::TTime()
  125. {
  126.   time_t ltime;
  127.   time(<ime);
  128.   struct tm _FAR *t = localtime(<ime);
  129.  
  130.   // Construct the date.  The time struct returns int, so casts are used.
  131.  
  132.   TDate today( (DayTy)t->tm_mday,
  133.                (MonthTy)(t->tm_mon + 1),
  134.                (YearTy)t->tm_year );
  135.  
  136.   *this = TTime( today, 
  137.                  (HourTy)t->tm_hour, 
  138.                  (MinuteTy)t->tm_min, 
  139.                  (SecondTy)t->tm_sec );
  140.  
  141. // Specified time and today's date:
  142. TTime::TTime( HourTy h, MinuteTy m, SecondTy s )
  143. {
  144.     Sec = TTime( TDate(),h,m,s ).Sec;
  145. }
  146.  
  147. /*
  148.  * Construct a Time for the specified (local) Date, hour, minute, and second.
  149.  * Note: this algorithm will fail if DST correction is something other
  150.  * than an hour.
  151.  * It is complicated by the DST boundary problem: 
  152.  * 1) Times in the phantom zone between 2AM and 3AM when DST is invoked are invalid.
  153.  * 2) Times in the hour after 1AM when DST ends, are redundant.
  154.  * Checking for these situations necessitates a lot of jumping back 
  155.  * and forth by an hour to check for the boundary.
  156.  */
  157. TTime::TTime( const TDate _BIDSFAR & date, HourTy h, MinuteTy m, SecondTy s )
  158. {
  159.     if( date.IsValid() )
  160.         {
  161.         Sec =   SECONDS_IN_DAY  * (date-RefDate) + 
  162.                 SECONDS_IN_HOUR * (h-1L) +    /* Note the adjustment by one hour */
  163.                 SECONDS_IN_MIN  * m + s;
  164.         if( Sec )
  165.             Sec += timezone;           // Adjust to GMT.
  166.  
  167.         if( IsDST() )
  168.             {
  169.             Sec += SECONDS_IN_HOUR;
  170.             if( IsDST() ) 
  171.                 Sec -= SECONDS_IN_HOUR;
  172.             }
  173.         else
  174.             {
  175.             Sec += SECONDS_IN_HOUR;
  176.             if( IsDST() ) 
  177.                 Sec = 0;            // Invalid "phantom" time.
  178.             }
  179.         }
  180.     else
  181.         Sec = 0;    // Invalid date
  182. }
  183.  
  184. /*************** conversion from TTime to TDate *******************/
  185.  
  186. // Type conversion to date.
  187. TDate::TDate( const TTime _BIDSFAR & t )
  188. {
  189.     Julnum = t.IsValid() ? jul1901 + (JulTy)(t.LocalSecs()/SECONDS_IN_DAY) : 0;
  190. }
  191.  
  192. /********************* public member functions **********************/
  193.  
  194. int TTime::CompareTo( const TTime _BIDSFAR &t ) const
  195. {
  196.     ClockTy diff = Sec - t.Sec;
  197.     return diff==0 ? 0 : diff>0 ? 1 : -1;
  198. }
  199.  
  200. // Hash function:
  201. unsigned TTime::Hash() const
  202. {
  203.     return (unsigned)Sec;
  204. }
  205.  
  206. /*
  207.  * The hour in local time:
  208.  */
  209. HourTy TTime::Hour() const
  210. {
  211.     return HourTy((LocalSecs() % SECONDS_IN_DAY) / SECONDS_IN_HOUR);
  212. }
  213.  
  214. /*
  215.  * The hour in GMT:
  216.  */
  217. HourTy TTime::HourGMT() const 
  218. {
  219.     return HourTy((Sec % SECONDS_IN_DAY) / SECONDS_IN_HOUR);
  220.  
  221. /*
  222.  * Return TRUE if DST is active for this time:
  223.  */
  224. int TTime::IsDST() const
  225. {
  226.   if( !daylight ) 
  227.     return 0;
  228.  
  229.   DayTy daycount = (unsigned)(Sec/SECONDS_IN_DAY);
  230.   YearTy year = TDate( (DayTy)daycount, (YearTy)0 ).Year();
  231.  
  232.   // Check to see if the time falls between the starting & stopping DST times.
  233.   return *this >= BeginDST( year ) && *this < EndDST( year );
  234. }
  235.  
  236. TTime TTime::Max( const TTime _BIDSFAR & t ) const 
  237. {
  238.     if( *this > t ) 
  239.         return *this;
  240.     else
  241.         return t;
  242. }
  243.  
  244. TTime TTime::Min( const TTime _BIDSFAR & t ) const 
  245. {
  246.     if( *this < t ) 
  247.         return *this;
  248.     else
  249.         return t;
  250. }
  251.  
  252. /*
  253.  * minute, in local time
  254.  */
  255. MinuteTy TTime::Minute() const
  256. {
  257.     return MinuteTy(((LocalSecs()%SECONDS_IN_DAY)%SECONDS_IN_HOUR)/SECONDS_IN_MIN);
  258. }
  259.  
  260. /*
  261.  * minute: GMT
  262.  */
  263. MinuteTy TTime::MinuteGMT() const 
  264. {
  265.     return MinuteTy(((Sec%SECONDS_IN_DAY)%SECONDS_IN_HOUR)/SECONDS_IN_MIN);
  266.  
  267. // second;local time or GMT 
  268. SecondTy TTime::Second() const 
  269. {
  270.     return SecondTy(((Sec%SECONDS_IN_DAY)%SECONDS_IN_HOUR)%SECONDS_IN_MIN);
  271. }
  272.  
  273.