Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

BdbTime.hh

Go to the documentation of this file.
00001 #ifndef BDBTIME_HH
00002 #define BDBTIME_HH
00003 
00004 //-----------------------------------------------------------------------------
00005 //
00006 // File and Version Information:
00007 //      $Id: BdbTime.hh,v 1.21 2004/08/06 05:48:02 bartoldu Exp $
00008 //
00009 // Description:
00010 //      Class BdbTime.  
00011 //      This is a persistent time class.
00012 //
00013 // Environment:
00014 //      Software developed for the BaBar Detector at the SLAC B-Factory.
00015 //
00016 // Author List:
00017 //      J. Ohnemus                      Original Author
00018 //      Gregory Dubois-Felsmann         Rogue Wave migration, 2002/2003
00019 //
00020 // Copyright Information:
00021 //      Copyright (C) 1994, 1995        Lawrence Berkeley Laboratory
00022 //      Copyright (c) 2002, 2003        California Institute of Technology
00023 //
00024 //-----------------------------------------------------------------------------
00025 
00026 //-----------------
00027 // BaBar Headers --
00028 //-----------------
00029 #include "BaBar/BaBarODMGTypes.h"
00030 
00031 //-----------------
00032 // C/C++ Headers --
00033 //-----------------
00034 #include <time.h>
00035 #include <iostream>
00036 #include <string>
00037 
00038 //-------------------------------
00039 // Collaborating Class Headers --
00040 //-------------------------------
00041 #include "BdbTime/BdbDuration.hh"
00042 #include "BdbTime/BdbTimeConst.hh"
00043 
00044 //------------------------------------
00045 // Collaborating Class Declarations --
00046 //------------------------------------
00047 
00048 //              ---------------------
00049 //              -- Class Interface --
00050 //              ---------------------
00051 
00052 class BdbTime {
00053 
00054 public:
00055 
00056   enum Zone { Local, UTC };
00057 
00058   // Constructors
00059 
00060   /**
00061    *  (Deprecated)
00062    *  Constructs with the current time, to the nearest second.  This
00063    *  constructor is deprecated and may be removed in a future release.
00064    *  The static function BdbTime::now() should be used in preference
00065    *  to this in all new code, if the current time is really required.
00066    *
00067    *  For some reason, the original implementation did not set the _gmtNsec
00068    *  member, perhaps because it was not easy to get it synchronized with
00069    *  the Rogue Wave "now()" function's return value.  Now that we use
00070    *  clock_gettime() directly, this could be fixed.
00071    *
00072    *  However, we have decided not to do this at this time, in order not
00073    *  to change the behavior of existing programs.
00074    *
00075    *  BdbTime::now() preserves the full significance available from
00076    *  clock_gettime().
00077    *
00078    *  Please note that this constructor involves a system call and is
00079    *  expensive!  Do not default-construct BdbTimes unless you really need
00080    *  the current time value.  If you are just declaring a time variable
00081    *  to fill in later, BdbTime(0) is a more performant choice.
00082    */
00083   BdbTime( );
00084 
00085   /** Copy constructor. */
00086   BdbTime( const BdbTime& t );
00087 
00088   /** 
00089    *  Constructs a time from an unsigned number of seconds since the
00090    *  BdbTime epoch of 1901.  NB: this is not the Unix epoch of 1970!
00091    */
00092   explicit BdbTime( d_ULong sec_since_1901, d_ULong nsec = 0 );
00093 
00094   /**
00095    *  Constructs a time from a broken-down list of components of a date
00096    *  and time.
00097    *
00098    *  This uses definitions inherited from the old RogueWave implementation
00099    *  of BdbTime.  Thus "year" is the calendar year C.E. (e.g., 2003), and
00100    *  "month" is the month in the range {1..12}.  Note that these differ 
00101    *  from the POSIX broken-down time (struct tm) definitions, where
00102    *  2003 C.E. is represented as 103, and the month is in the range {0..11}.
00103    */
00104   BdbTime( d_ULong year,
00105            d_ULong month,
00106            d_ULong day,
00107            d_ULong hour,
00108            d_ULong minute,
00109            d_ULong second,
00110            d_ULong nanosecond = 0,
00111            Zone zone = UTC );
00112 
00113   /**
00114    *  (Deprecated - use parseTime())
00115    *  Constructs a BdbTime from a string date and a string time.
00116    *
00117    *  The use of this constructor is strongly discouraged, as it does not
00118    *  have a means of reliably reporting parsing errors (BaBar does not
00119    *  use C++ exceptions).  Use BdbTime::parseTime() instead (which this
00120    *  is implemented over).
00121    */
00122   BdbTime( const std::string& date, const std::string& time, Zone zone = UTC );
00123 
00124   /**
00125    *  (Deprecated - use parseTime())
00126    *  Constructs a BdbTime from a single date-time string, in which the
00127    *  date and time must be given separated by whitespace.  Otherwise
00128    *  identical to the above constructor.
00129    *
00130    *  The use of this constructor is strongly discouraged, as it does not
00131    *  have a means of reliably reporting parsing errors (BaBar does not
00132    *  use C++ exceptions).  Use BdbTime::parseTime() instead (which this
00133    *  is implemented over).
00134    */
00135   explicit BdbTime( const std::string&, Zone zone = UTC );
00136 
00137   /** 
00138    *  Constructs from POSIX high-resolution time, as might be
00139    *  obtained from clock_gettime.
00140    */
00141   BdbTime( const struct timespec& ts );
00142 
00143   /**
00144    *  Constructs from POSIX "broken-down time".
00145    *  @param stm Cannot be const because it is internally provided to
00146    *             POSIX mktime(), which normalizes it -- see man mktime.
00147    */
00148   BdbTime( struct tm& stm, Zone zone = UTC );
00149 
00150   /**
00151    *  The destructor is non-virtual in order to keep this representational
00152    *  class small and suitable for processing with value semantics.
00153    *  Classes with non-empty destructors should not be constructed with
00154    *  non-private inheritance from BdbTime.
00155    */
00156   ~BdbTime( ) { }
00157 
00158 
00159   // Assignment operator
00160   BdbTime&    operator=( const BdbTime& t );
00161     
00162   // Calculational operators
00163   
00164   /**
00165    *   Calculates the absolute value of the difference between two times.
00166    *   NB: BdbDuration is an inherently unsigned quantity!  This is
00167    *   in essence because reasonably foreseeable time differences are
00168    *   larger in seconds than 2^31 and so can't be represented as a
00169    *   signed 32 bit integer.
00170    */
00171   BdbDuration operator-(  const BdbTime& t ) const;               
00172 
00173   BdbTime&    operator+=( const BdbDuration& d );
00174   BdbTime     operator+(  const BdbDuration& d ) const;
00175 
00176   BdbTime&    operator-=( const BdbDuration& d );
00177   BdbTime     operator-(  const BdbDuration& d ) const;
00178 
00179   // Comparison operators
00180   bool operator==( const BdbTime& t ) const
00181     { 
00182       return ( _gmtSec  == t._gmtSec && _gmtNsec == t._gmtNsec );
00183     }
00184 
00185   bool operator!=( const BdbTime& t ) const
00186     { 
00187       return !( *this == t ); 
00188     }
00189 
00190   bool operator<(  const BdbTime& t ) const
00191     { 
00192       return ( _gmtSec  < t._gmtSec ) ||        
00193              ( _gmtSec == t._gmtSec   && _gmtNsec < t._gmtNsec );
00194     }
00195 
00196   bool operator<=( const BdbTime& t ) const
00197     { 
00198       return ( _gmtSec  < t._gmtSec )  ||
00199              ( _gmtSec == t._gmtSec    && _gmtNsec <= t._gmtNsec );
00200     }
00201     
00202   bool operator>(  const BdbTime& t ) const
00203     { 
00204       return !( *this <= t ); 
00205     }
00206 
00207   bool operator>=( const BdbTime& t ) const
00208     { 
00209       return !( *this <  t ); 
00210     }
00211   
00212   // Selectors
00213   d_ULong getGmtSec( )  const { return _gmtSec;  }
00214   d_ULong getGmtNsec( ) const { return _gmtNsec; }
00215 
00216   /**
00217    *  Extracts the value of the BdbTime as a POSIX.1b "struct timespec".
00218    *  Returns 0 on success in analogy with POSIX.1b clock_gettime().
00219    *  WARNING: Must and will fail for valid BdbTime values that are more
00220    *  than 2^31-1 seconds before the beginning of the POSIX 1970 epoch,
00221    *  i.e., before around 1901.12.13 20:45:53 UTC.
00222    *
00223    *  There are such times in the conditions database from early 
00224    *  SP production, before all times were renormalized into 1997+ space.
00225    */
00226   int timeSpec( struct timespec* ts ) const;
00227 
00228   /**
00229    *  Extracts the value of the BdbTime as a POSIX "struct tm" broken-down
00230    *  time.  This requires the use of a time zone.  In analogy with the
00231    *  POSIX.1b gmtime_r() function, a pointer to a "struct tm" to receive
00232    *  the data must be supplied -- so this function is thread-safe(*).
00233    *  Following this analogy, the function returns the supplied pointer
00234    *  on success, and 0 on failure.
00235    *
00236    *  This function should work for all times in the BdbTime range.
00237    */
00238   struct tm* tm( struct tm* stm, Zone zone ) const;
00239 
00240   /**
00241    *  Creates a string from the value of the BdbTime, based on a 
00242    *  specified format specification, as for POSIX strftime(), and on
00243    *  a time zone.  Note that this function does not provide a way 
00244    *  to embed the "nanoseconds" part of the BdbTime, since this is
00245    *  not possible to express in a form recognized by strftime.
00246    *
00247    *  The "%N" format specified does not appear to be used in the POSIX
00248    *  definition of strftime.  It's possible it could be hijacked in a
00249    *  future upgrade.                                                   FIXME
00250    *
00251    *  This function should work for all times in the BdbTime range.
00252    */
00253   std::string asString( const char* fmt, Zone zone ) const;
00254 
00255   // Friends
00256   friend BdbTime  operator+( const BdbDuration& d, const BdbTime& t );
00257   friend std::ostream& operator<<( std::ostream& os, const BdbTime& t );
00258 
00259 private:
00260 
00261   void renormalizeNanoseconds( );
00262 
00263   // Data members
00264   d_ULong _gmtSec;   // number of seconds since 00:00:00 Jan. 1, 1901 UTC
00265   d_ULong _gmtNsec;  // number of nanoseconds
00266 
00267 public:
00268   // static interfaces:
00269 
00270   /**
00271    *  Constructs and returns a BdbTime representing the current time.
00272    *  This interface, unlike the deprecated default constructor, returns
00273    *  a BdbTime set to the full resolution available from clock_gettime().
00274    *  Note that this may vary between platforms and even operating
00275    *  system versions.
00276    */
00277   static BdbTime now();
00278 
00279   /**
00280    *  Determines whether a string representing a date and a string
00281    *  representing a time can be converted successfully to a date/time
00282    *  in BdbTime format, i.e., in the unsigned 1901 epoch.
00283    *
00284    *  Note that 1901.01.01 00:00:00 UTC is not a valid time; 00:00:01
00285    *  is the first valid time.
00286    *
00287    *  Date is parsed using strptime formats "%D" and "%d%b%Y", controlled
00288    *  by BdbTimeInput, with the first one that succeeds taking precedence.
00289    *  Time is parsed with formats "%T" and "%R".  These are quite a
00290    *  restricted set compared to those originally accepted by the
00291    *  Rogue Wave implementation first used here.
00292    *
00293    *  By default times are interpreted as UTC (a logical alternative might 
00294    *  be the local time zone.  If an invalid date or time string is supplied,
00295    *  the BdbTime time will be set to -Infinity.  If the date string is set to 
00296    *  "+Infinity" or "-Infinity", the time string will be ignored and the
00297    *  BdbTime will be set to the corresponding value.
00298    *
00299    *  @param time Returned time value; modified only if parsing is successful.
00300    *  @return Flag indicating whether parsing was successful.
00301    */
00302   static bool parseTime( const std::string& sdate, const std::string& stime, 
00303                          Zone zone,
00304                          BdbTime& time );
00305 
00306   /**
00307    *  Determines whether a string representing a date and time can be
00308    *  converted successfully to a date/time in BdbTime format, i.e., in
00309    *  the unsigned 1901 epoch.
00310    *
00311    *  Equivalent to a call to parseTime( const std::string& sdate, 
00312    *    const std::string& stime, Zone zone, BdbTime& time )
00313    *  with the date and time set from the first and second whitespace-
00314    *  delimited tokens in the sdatetime string and subsequent text ignored.
00315    *
00316    *  This is a less precise parsing method than the above.
00317    *
00318    *  @param time Returned time value; modified only if parsing is successful.
00319    *  @return Flag indicating whether parsing was successful.
00320    */
00321   static bool parseTime( const std::string& sdatetime, 
00322                          Zone zone,
00323                          BdbTime& time );
00324 
00325   // Static members
00326   static const BdbTime minusInfinity;
00327   static const BdbTime plusInfinity;
00328 
00329 };
00330 
00331 
00332 inline void
00333 BdbTime::renormalizeNanoseconds( )
00334 {
00335   if ( _gmtNsec >= BdbTimeConst::nsecInASec ) {
00336     // carry nanoseconds over into seconds
00337     d_ULong extraSec   = _gmtNsec / BdbTimeConst::nsecInASec;
00338     d_ULong remainNsec = _gmtNsec % BdbTimeConst::nsecInASec;
00339     _gmtSec            += extraSec;
00340     _gmtNsec           =  remainNsec;
00341   } 
00342 }
00343 
00344 #endif

Generated on Mon Dec 5 18:21:58 2005 for CDB by doxygen1.3-rc3