// @(#)root/base:$Id$
// Author: R. Hatcher   30/9/2001

/*************************************************************************
 * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TTimeStamp
#define ROOT_TTimeStamp

//////////////////////////////////////////////////////////////////////////
//
// The TTimeStamp encapsulates seconds and ns since EPOCH
//
// This extends (and isolates) struct timespec
//    struct timespec
//       {
//          time_t   tv_sec;   /* seconds */
//          long     tv_nsec;  /* nanoseconds */
//       }
//    time_t seconds is relative to Jan 1, 1970 00:00:00 UTC
//
// No accounting of leap seconds is made.
//
// Due to ROOT/CINT limitations TTimeStamp does not explicitly
// hold a timespec struct; attempting to do so means the Streamer
// must be hand written.  Instead we have chosen to simply contain
// similar fields within the private area of this class.
//
// NOTE: the use of time_t (and its default implementation as a 32 int)
//       implies overflow conditions occurs somewhere around
//       Jan 18, 19:14:07, 2038.
//       If this experiment is still going when it becomes significant
//       someone will have to deal with it.
//
//////////////////////////////////////////////////////////////////////////

#ifndef ROOT_Rtypes
#include "Rtypes.h"
#endif
#ifndef ROOT_Riosfwd
#include "Riosfwd.h"
#endif

#include <time.h>
#if !defined(__CINT__) && (defined(R__MACOSX) || defined(R__OBSD))
#include <sys/time.h>
#endif
#if defined(__CINT__) || defined(R__WIN32)
// Explicit definition of timespec 'cause "rootcint" won't look in
// appropriate <time.h>. time_t appears to be defined as "typedef long time_t;"
// in CINT version of <time.h>.  This isn't required by the standard:
// to be compatible w/ std functions it must be at least 32-bits long,
// but it might be longer to avoid the year-2037 cutoff.
struct timespec
{
   time_t   tv_sec;             // seconds
   long     tv_nsec;            // nanoseconds
};
#endif
#if defined(__CINT__)
struct tm
{
   int tm_sec;                   // Seconds.     [0-60] (1 leap second)
   int tm_min;                   // Minutes.     [0-59]
   int tm_hour;                  // Hours.       [0-23]
   int tm_mday;                  // Day.         [1-31]
   int tm_mon;                   // Month.       [0-11]
   int tm_year;                  // Year - 1900.
   int tm_wday;                  // Day of week. [0-6]
   int tm_yday;                  // Days in year.[0-365]
   int tm_isdst;                 // DST.         [-1/0/1]
};
#endif

// define this typedef so that CINT doesn't barf at using these
// for function return values
typedef struct timespec timespec_t;
typedef struct tm       tm_t;

class TVirtualMutex;
class TTimeStamp;
std::ostream &operator<<(std::ostream &os,  const TTimeStamp &ts);
TBuffer &operator<<(TBuffer &buf, const TTimeStamp &ts);
TBuffer &operator>>(TBuffer &buf, TTimeStamp &ts);
Bool_t operator==(const TTimeStamp &lhs, const TTimeStamp &rhs);
Bool_t operator!=(const TTimeStamp &lhs, const TTimeStamp &rhs);
Bool_t operator< (const TTimeStamp &lhs, const TTimeStamp &rhs);
Bool_t operator<=(const TTimeStamp &lhs, const TTimeStamp &rhs);
Bool_t operator> (const TTimeStamp &lhs, const TTimeStamp &rhs);
Bool_t operator>=(const TTimeStamp &lhs, const TTimeStamp &rhs);

R__EXTERN TVirtualMutex *gTimeMutex;

class TTimeStamp {

friend Bool_t operator==(const TTimeStamp &lhs, const TTimeStamp &rhs);
friend Bool_t operator!=(const TTimeStamp &lhs, const TTimeStamp &rhs);
friend Bool_t operator< (const TTimeStamp &lhs, const TTimeStamp &rhs);
friend Bool_t operator<=(const TTimeStamp &lhs, const TTimeStamp &rhs);
friend Bool_t operator> (const TTimeStamp &lhs, const TTimeStamp &rhs);
friend Bool_t operator>=(const TTimeStamp &lhs, const TTimeStamp &rhs);

private:
   Int_t  fSec;      // seconds
   Int_t  fNanoSec;  // nanoseconds

   void   NormalizeNanoSec();

public:
   // empty ctor (builds current time with nsec field incremented from static)
   TTimeStamp();

   // construction from timespec struct
   TTimeStamp(const timespec_t &ts) :
      fSec(Int_t(ts.tv_sec)), fNanoSec(ts.tv_nsec) { NormalizeNanoSec(); }

   // construction from time_t and separate nsec
   TTimeStamp(time_t t, Int_t nsec) :
      fSec(Int_t(t)), fNanoSec(nsec) { NormalizeNanoSec(); }

   // construction from bits and pieces
   TTimeStamp(UInt_t year, UInt_t month,
              UInt_t day,  UInt_t hour,
              UInt_t min,  UInt_t sec,
              UInt_t nsec = 0, Bool_t isUTC = kTRUE, Int_t secOffset = 0);

   // compatibility with TDatime
   TTimeStamp(UInt_t date, UInt_t time, UInt_t nsec,
              Bool_t isUTC = kTRUE, Int_t secOffset = 0);

   // compatability with time() and DOS date
   TTimeStamp(UInt_t tloc, Bool_t isUTC = kTRUE, Int_t secOffset = 0,
              Bool_t dosDate = kFALSE);

   virtual ~TTimeStamp() { }

   // initialize to current time with nsec field incremented from static
   void Set();

   // construction from bits and pieces
   void Set(Int_t year, Int_t month,  Int_t day,
            Int_t hour, Int_t min,    Int_t sec,
            Int_t nsec, Bool_t isUTC, Int_t secOffset);

   // compatibility with TDatime
   void Set(Int_t date,   Int_t time, Int_t nsec,
            Bool_t isUTC, Int_t secOffset);

   // compatability with time() and DOS date
   void Set(UInt_t tloc, Bool_t isUTC, Int_t secOffset, Bool_t dosDate);

   // direct setters
   void SetSec(Int_t sec) { fSec = sec; }
   void SetNanoSec(Int_t nsec) { fNanoSec = nsec; }

   timespec_t   GetTimeSpec() const
      { timespec_t value = {fSec,fNanoSec}; return value; }
   time_t       GetSec() const { return fSec; }
   Int_t        GetNanoSec() const { return fNanoSec; }

   Double_t     AsDouble() const { return fSec + 1e-9 * fNanoSec; }
   Double_t     AsJulianDate() const { return (AsDouble()/86400.0 + 2440587.5); }
   const char  *AsString(const Option_t *option="") const;

   void         Copy(TTimeStamp &ts) const;
   UInt_t       GetDate(Bool_t inUTC = kTRUE, Int_t secOffset = 0,
                        UInt_t *year = 0, UInt_t *month = 0,
                        UInt_t *day = 0) const;
   UInt_t       GetTime(Bool_t inUTC = kTRUE, Int_t secOffset = 0,
                        UInt_t *hour = 0, UInt_t *min = 0,
                        UInt_t *sec = 0) const;
   Int_t        GetDayOfYear(Bool_t inUTC = kTRUE, Int_t secOffset = 0) const;
   Int_t        GetDayOfWeek(Bool_t inUTC = kTRUE, Int_t secOffset = 0) const;
   Int_t        GetMonth(Bool_t inUTC = kTRUE, Int_t secOffset = 0) const;
   Int_t        GetWeek(Bool_t inUTC = kTRUE, Int_t secOffset = 0) const;
   Bool_t       IsLeapYear(Bool_t inUTC = kTRUE, Int_t secOffset = 0) const;

   void         Add(const TTimeStamp &offset);

   void         Print(const Option_t *option="") const;

   operator double() const { return AsDouble(); }

   // Utility functions
   static Int_t   GetZoneOffset();
   static time_t  MktimeFromUTC(tm_t *tmstruct);
   static void    DumpTMStruct(const tm_t &tmstruct);
   static Int_t   GetDayOfYear(Int_t day, Int_t month, Int_t year);
   static Int_t   GetDayOfWeek(Int_t day, Int_t month, Int_t year);
   static Int_t   GetWeek(Int_t day, Int_t month, Int_t year);
   static Bool_t  IsLeapYear(Int_t year);

   ClassDef(TTimeStamp,1)  //Encapsulates seconds and ns since EPOCH
};


inline Bool_t operator==(const TTimeStamp &lhs, const TTimeStamp &rhs)
   { return lhs.fSec == rhs.fSec &&
            lhs.fNanoSec == rhs.fNanoSec; }

inline Bool_t operator!=(const TTimeStamp &lhs, const TTimeStamp &rhs)
   { return lhs.fSec != rhs.fSec ||
            lhs.fNanoSec != rhs.fNanoSec; }

inline Bool_t operator<(const TTimeStamp &lhs, const TTimeStamp &rhs)
   { return lhs.fSec < rhs.fSec ||
             (lhs.fSec == rhs.fSec &&
              lhs.fNanoSec < rhs.fNanoSec); }

inline Bool_t operator<=(const TTimeStamp &lhs, const TTimeStamp &rhs)
   { return lhs.fSec < rhs.fSec ||
             (lhs.fSec == rhs.fSec &&
              lhs.fNanoSec <= rhs.fNanoSec); }

inline Bool_t operator>(const TTimeStamp &lhs, const TTimeStamp &rhs)
   { return lhs.fSec > rhs.fSec ||
             (lhs.fSec == rhs.fSec &&
              lhs.fNanoSec > rhs.fNanoSec); }

inline Bool_t operator>=(const TTimeStamp &lhs, const TTimeStamp &rhs)
   { return lhs.fSec > rhs.fSec ||
             (lhs.fSec == rhs.fSec &&
              lhs.fNanoSec >= rhs.fNanoSec); }

#endif
 TTimeStamp.h:1
 TTimeStamp.h:2
 TTimeStamp.h:3
 TTimeStamp.h:4
 TTimeStamp.h:5
 TTimeStamp.h:6
 TTimeStamp.h:7
 TTimeStamp.h:8
 TTimeStamp.h:9
 TTimeStamp.h:10
 TTimeStamp.h:11
 TTimeStamp.h:12
 TTimeStamp.h:13
 TTimeStamp.h:14
 TTimeStamp.h:15
 TTimeStamp.h:16
 TTimeStamp.h:17
 TTimeStamp.h:18
 TTimeStamp.h:19
 TTimeStamp.h:20
 TTimeStamp.h:21
 TTimeStamp.h:22
 TTimeStamp.h:23
 TTimeStamp.h:24
 TTimeStamp.h:25
 TTimeStamp.h:26
 TTimeStamp.h:27
 TTimeStamp.h:28
 TTimeStamp.h:29
 TTimeStamp.h:30
 TTimeStamp.h:31
 TTimeStamp.h:32
 TTimeStamp.h:33
 TTimeStamp.h:34
 TTimeStamp.h:35
 TTimeStamp.h:36
 TTimeStamp.h:37
 TTimeStamp.h:38
 TTimeStamp.h:39
 TTimeStamp.h:40
 TTimeStamp.h:41
 TTimeStamp.h:42
 TTimeStamp.h:43
 TTimeStamp.h:44
 TTimeStamp.h:45
 TTimeStamp.h:46
 TTimeStamp.h:47
 TTimeStamp.h:48
 TTimeStamp.h:49
 TTimeStamp.h:50
 TTimeStamp.h:51
 TTimeStamp.h:52
 TTimeStamp.h:53
 TTimeStamp.h:54
 TTimeStamp.h:55
 TTimeStamp.h:56
 TTimeStamp.h:57
 TTimeStamp.h:58
 TTimeStamp.h:59
 TTimeStamp.h:60
 TTimeStamp.h:61
 TTimeStamp.h:62
 TTimeStamp.h:63
 TTimeStamp.h:64
 TTimeStamp.h:65
 TTimeStamp.h:66
 TTimeStamp.h:67
 TTimeStamp.h:68
 TTimeStamp.h:69
 TTimeStamp.h:70
 TTimeStamp.h:71
 TTimeStamp.h:72
 TTimeStamp.h:73
 TTimeStamp.h:74
 TTimeStamp.h:75
 TTimeStamp.h:76
 TTimeStamp.h:77
 TTimeStamp.h:78
 TTimeStamp.h:79
 TTimeStamp.h:80
 TTimeStamp.h:81
 TTimeStamp.h:82
 TTimeStamp.h:83
 TTimeStamp.h:84
 TTimeStamp.h:85
 TTimeStamp.h:86
 TTimeStamp.h:87
 TTimeStamp.h:88
 TTimeStamp.h:89
 TTimeStamp.h:90
 TTimeStamp.h:91
 TTimeStamp.h:92
 TTimeStamp.h:93
 TTimeStamp.h:94
 TTimeStamp.h:95
 TTimeStamp.h:96
 TTimeStamp.h:97
 TTimeStamp.h:98
 TTimeStamp.h:99
 TTimeStamp.h:100
 TTimeStamp.h:101
 TTimeStamp.h:102
 TTimeStamp.h:103
 TTimeStamp.h:104
 TTimeStamp.h:105
 TTimeStamp.h:106
 TTimeStamp.h:107
 TTimeStamp.h:108
 TTimeStamp.h:109
 TTimeStamp.h:110
 TTimeStamp.h:111
 TTimeStamp.h:112
 TTimeStamp.h:113
 TTimeStamp.h:114
 TTimeStamp.h:115
 TTimeStamp.h:116
 TTimeStamp.h:117
 TTimeStamp.h:118
 TTimeStamp.h:119
 TTimeStamp.h:120
 TTimeStamp.h:121
 TTimeStamp.h:122
 TTimeStamp.h:123
 TTimeStamp.h:124
 TTimeStamp.h:125
 TTimeStamp.h:126
 TTimeStamp.h:127
 TTimeStamp.h:128
 TTimeStamp.h:129
 TTimeStamp.h:130
 TTimeStamp.h:131
 TTimeStamp.h:132
 TTimeStamp.h:133
 TTimeStamp.h:134
 TTimeStamp.h:135
 TTimeStamp.h:136
 TTimeStamp.h:137
 TTimeStamp.h:138
 TTimeStamp.h:139
 TTimeStamp.h:140
 TTimeStamp.h:141
 TTimeStamp.h:142
 TTimeStamp.h:143
 TTimeStamp.h:144
 TTimeStamp.h:145
 TTimeStamp.h:146
 TTimeStamp.h:147
 TTimeStamp.h:148
 TTimeStamp.h:149
 TTimeStamp.h:150
 TTimeStamp.h:151
 TTimeStamp.h:152
 TTimeStamp.h:153
 TTimeStamp.h:154
 TTimeStamp.h:155
 TTimeStamp.h:156
 TTimeStamp.h:157
 TTimeStamp.h:158
 TTimeStamp.h:159
 TTimeStamp.h:160
 TTimeStamp.h:161
 TTimeStamp.h:162
 TTimeStamp.h:163
 TTimeStamp.h:164
 TTimeStamp.h:165
 TTimeStamp.h:166
 TTimeStamp.h:167
 TTimeStamp.h:168
 TTimeStamp.h:169
 TTimeStamp.h:170
 TTimeStamp.h:171
 TTimeStamp.h:172
 TTimeStamp.h:173
 TTimeStamp.h:174
 TTimeStamp.h:175
 TTimeStamp.h:176
 TTimeStamp.h:177
 TTimeStamp.h:178
 TTimeStamp.h:179
 TTimeStamp.h:180
 TTimeStamp.h:181
 TTimeStamp.h:182
 TTimeStamp.h:183
 TTimeStamp.h:184
 TTimeStamp.h:185
 TTimeStamp.h:186
 TTimeStamp.h:187
 TTimeStamp.h:188
 TTimeStamp.h:189
 TTimeStamp.h:190
 TTimeStamp.h:191
 TTimeStamp.h:192
 TTimeStamp.h:193
 TTimeStamp.h:194
 TTimeStamp.h:195
 TTimeStamp.h:196
 TTimeStamp.h:197
 TTimeStamp.h:198
 TTimeStamp.h:199
 TTimeStamp.h:200
 TTimeStamp.h:201
 TTimeStamp.h:202
 TTimeStamp.h:203
 TTimeStamp.h:204
 TTimeStamp.h:205
 TTimeStamp.h:206
 TTimeStamp.h:207
 TTimeStamp.h:208
 TTimeStamp.h:209
 TTimeStamp.h:210
 TTimeStamp.h:211
 TTimeStamp.h:212
 TTimeStamp.h:213
 TTimeStamp.h:214
 TTimeStamp.h:215
 TTimeStamp.h:216
 TTimeStamp.h:217
 TTimeStamp.h:218
 TTimeStamp.h:219
 TTimeStamp.h:220
 TTimeStamp.h:221
 TTimeStamp.h:222
 TTimeStamp.h:223
 TTimeStamp.h:224
 TTimeStamp.h:225
 TTimeStamp.h:226
 TTimeStamp.h:227
 TTimeStamp.h:228
 TTimeStamp.h:229
 TTimeStamp.h:230