Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

VldTimeStamp.cxx

Go to the documentation of this file.
00001 
00002 // $Id: VldTimeStamp.cxx,v 1.25 2005/06/02 16:53:36 rhatcher Exp $
00003 //
00004 // The VldTimeStamp encapsulates the seconds and ns since EPOCH
00005 //
00006 // This extends (and isolates) struct timespec
00007 //    struct timespec
00008 //       {
00009 //          time_t   tv_sec;   /* seconds */
00010 //          long     tv_nsec;  /* nanoseconds */
00011 //       }
00012 //    time_t seconds is relative to Jan 1, 1970 00:00:00 UTC
00013 //
00014 // Due to ROOT/CINT limitations VldTimeStamp does not explicitly
00015 // hold a timespec struct; attempting to do so means the Streamer
00016 // must be hand written.  Instead we have chosen to simply contain
00017 // similar fields within the private area of this class.
00018 //
00019 // NOTE: the use of time_t (and its default implementation as a 32 int)
00020 //       implies overflow conditions occurs somewhere around
00021 //       Jan 18, 19:14:07, 2038.
00022 //       If this experiment is still going when it becomes significant
00023 //       someone will have to deal with it.
00024 //
00025 // Author:  R. Hatcher 2000.04.19
00026 //          R. Hatcher 2000.12.20 -- convert from TDatime to struct timespec
00027 //
00029 
00030 #include "Validity/VldTimeStamp.h"
00031 
00032 #include "MessageService/MsgService.h"
00033 CVSID("$Id: VldTimeStamp.cxx,v 1.25 2005/06/02 16:53:36 rhatcher Exp $");
00034 
00035 #ifdef R__WIN32
00036 #include "Windows4Root.h"
00037 #else
00038 #include <unistd.h>
00039 // timeval, timezone, gettimeofday
00040 #include <sys/time.h>
00041 #endif
00042 
00043 #include "TString.h"
00044 
00045 ClassImp(VldTimeStamp)
00046 
00047 const Int_t kNsPerSec = 1000000000;
00048 
00049 //_____________________________________________________________________________
00050 std::ostream& operator<<(std::ostream& os, const VldTimeStamp& ts) 
00051 {
00052    if (os.good()) {
00053       if (os.tie()) os.tie()->flush(); // instead of opfx
00054       os << ts.AsString("c");
00055    }
00056    // instead of os.osfx()
00057    if (os.flags() & std::ios::unitbuf) os.flush();
00058    return os;
00059 }
00060 
00061 VldTimeStamp VldTimeStamp::GetBOT()
00062 {
00063     return VldTimeStamp(0,0);
00064 }
00065 
00066 VldTimeStamp VldTimeStamp::GetEOT()
00067 {
00068     return VldTimeStamp((1<<31)-1,0);
00069 }
00070 
00071 
00072 //_____________________________________________________________________________
00073 // don't put these in the header or using the include file w/ CINT
00074 // become problematic
00075 
00076 // default ctor sets it value to current time (as best possible)
00077 VldTimeStamp::VldTimeStamp() { Set(); }
00078 VldTimeStamp::~VldTimeStamp() { ; }
00079 
00080 //_____________________________________________________________________________
00081 VldTimeStamp::VldTimeStamp(UInt_t year, UInt_t month,
00082                            UInt_t day,  UInt_t hour,
00083                            UInt_t min,  UInt_t sec,
00084                            UInt_t nsec, 
00085                            Bool_t isUTC, Int_t secOffset)
00086 {
00087    // Create a VldTimeStamp and set it to the specified year, month,
00088    // day, time, hour, minute, second and nanosec.
00089    // If !isUTC then it is assumed to be the standard local time zone.
00090    //
00091    // If local time is PST then one can use
00092    //    VldTimeStamp(year,month,day,hour,min,sec,nsec,kFALSE,0);
00093    // or
00094    //    Int_t secOffset = 8*60*60;
00095    //    VldTimeStamp(year,month,day,hour,min,sec,nsec,kTRUE,8*60*60);
00096    
00097    Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
00098 }
00099 
00100 //_____________________________________________________________________________
00101 VldTimeStamp::VldTimeStamp(UInt_t date, UInt_t time, UInt_t nsec, 
00102                            Bool_t isUTC, Int_t secOffset)
00103 {
00104    // Create a VldTimeStamp and set it to the specified date, time, nanosec.
00105    // If !isUTC then it is assumed to be the standard local time zone.
00106 
00107    Set(date, time, nsec, isUTC, secOffset);
00108 }
00109 
00110 //_____________________________________________________________________________
00111 const char *VldTimeStamp::AsString(Option_t *option) const
00112 {
00113    // Return the date & time as a string.
00114    //
00115    // Result is pointer to a statically allocated string.
00116    // User should copy this into their own buffer before calling
00117    // this method again.  This is somewhat mitigated
00118    // by use of a circular buffer of strings.
00119    //
00120    // Option "l" returns it in local zone format
00121    // (can be applied to default or compact format).
00122    //
00123    // Default format is RFC822 compliant:
00124    //   "Mon, 02 Jan 2001 18:11:12 +0000 (GMT) +999999999 nsec"
00125    //   "Mon, 02 Jan 2001 10:11:12 -0800 (PST) +999999999 nsec"
00126    //
00127    // Option "c" compact is (almost) ISO 8601 compliant:
00128    //   "2001-01-02 18:11:12.9999999999Z"
00129    //   "2001-01-02 10:11:12.9999999999-0800"  if PST
00130    //      * uses "-" as date separator as specified in ISO 8601
00131    //      * uses "." rather than preferred "," for decimal separator
00132    //      * -HHMM is the difference between local and UTC (if behind, + if ahead).
00133    //   The "-HHMM" is replaced with "Z" if given as UTC.
00134    //   To be strictly conforming it should use "T" instead of the
00135    //   blank separating the date and time.
00136    //
00137    // Option "2" returns as {sec,nsec} integers.
00138    //
00139    // Option "s" returns "2001-01-02 18:11:12" with an implied UTC,
00140    // overrides "l" option.
00141 
00142    // Internally uses a circular list of buffers to avoid problems
00143    // using AsString multiple times in a single statement.
00144 
00145    const int nbuffers = 8;     // # of buffers
00146 
00147    static char formatted[nbuffers][64];  // strftime fields substituted
00148    static char formatted2[nbuffers][64]; // nanosec field substituted
00149    static int ibuffer = nbuffers;
00150    ibuffer = (ibuffer+1)%nbuffers; // each call moves to next buffer
00151 
00152    TString opt = option;
00153    opt.ToLower();
00154 
00155    if (opt.Contains("2")) {
00156       // return string formatted as integer {sec,nsec}
00157       sprintf(formatted[ibuffer], "{%d,%d}", fSec, fNanoSec);
00158       return formatted[ibuffer];
00159    }
00160 
00161 #ifdef linux
00162    // under linux %z is the hour offset and %Z is the timezone name
00163    const char *RFC822   = "%a, %d %b %Y %H:%M:%S %z (%Z) +#9ld nsec";
00164    const char *ISO8601  = "%Y-%m-%d %H:%M:%S.#9.9ld%z";
00165    const char *ISO8601Z = "%Y-%m-%d %H:%M:%S.#9.9ldZ";
00166 #else
00167    // otherwise only %Z is guarenteed to be defind
00168    const char *RFC822   = "%a, %d %b %Y %H:%M:%S %Z +#9ld nsec";
00169    const char *ISO8601  = "%Y-%m-%d %H:%M:%S.#9.9ld%Z";
00170    const char *ISO8601Z = "%Y-%m-%d %H:%M:%S.#9.9ldZ";
00171 #endif
00172    const char *SQL = "%Y-%m-%d %H:%M:%S";
00173 
00174    Bool_t asLocal = opt.Contains("l");
00175    Bool_t asSQL   = opt.Contains("s");
00176    if (asSQL) asLocal = kFALSE;
00177 
00178    const char *format = RFC822;
00179    if (opt.Contains("c")) {
00180       format = ISO8601;
00181       if (!asLocal) format = ISO8601Z;
00182    }
00183    if (asSQL) format = SQL;
00184 
00185    struct tm *ptm;
00186    time_t seconds = (time_t) fSec;   // deal with possible mismatch of types 
00187                                      // of fSec and the time_t required 
00188                                      // by functions
00189 
00190    // get the components into a tm struct
00191    ptm = (asLocal) ? localtime(&seconds) : gmtime(&seconds);
00192 
00193    // format all but the nsec field
00194    // size_t length =
00195    strftime(formatted[ibuffer], sizeof(formatted[ibuffer]), format, ptm);
00196 
00197    if (asSQL) return formatted[ibuffer];
00198 
00199    // hack in the nsec part
00200    char *ptr = strrchr(formatted[ibuffer], '#');
00201    if (ptr) *ptr = '%';    // substitute % for #
00202    sprintf(formatted2[ibuffer], formatted[ibuffer], fNanoSec);
00203 
00204    return formatted2[ibuffer];
00205 }
00206 
00207 //_____________________________________________________________________________
00208 void VldTimeStamp::Copy(VldTimeStamp &ts) const
00209 {
00210    // Copy this to ts.
00211 
00212    ts.fSec     = fSec;
00213    ts.fNanoSec = fNanoSec;
00214 
00215 }
00216 
00217 //_____________________________________________________________________________
00218 Int_t VldTimeStamp::GetDate(Bool_t inUTC, Int_t secOffset,
00219                             UInt_t* year, UInt_t* month, UInt_t* day) const
00220 {
00221    // Return date in form of 19971224 (i.e. 24/12/1997),
00222    // if non-zero pointers supplied for year, month, day fill those as well
00223 
00224    time_t atime = fSec + secOffset;
00225    struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00226 
00227    if (year)  *year  = ptm->tm_year + 1900;
00228    if (month) *month = ptm->tm_mon + 1;
00229    if (day)   *day   = ptm->tm_mday;
00230 
00231    return (1900+ptm->tm_year)*10000 + (1+ptm->tm_mon)*100 + ptm->tm_mday;
00232 
00233 }
00234 
00235 //_____________________________________________________________________________
00236 Int_t VldTimeStamp::GetTime(Bool_t inUTC, Int_t secOffset,
00237                             UInt_t* hour, UInt_t* min, UInt_t* sec) const
00238 {
00239    // Return time in form of 123623 (i.e. 12:36:23),
00240    // if non-zero pointers supplied for hour, min, sec fill those as well
00241 
00242    time_t atime = fSec + secOffset;
00243    struct tm *ptm = (inUTC) ? gmtime(&atime) : localtime(&atime);
00244 
00245    if (hour) *hour = ptm->tm_hour;
00246    if (min)  *min  = ptm->tm_min;
00247    if (sec)  *sec  = ptm->tm_sec;
00248 
00249    return ptm->tm_hour*10000 + ptm->tm_min*100 + ptm->tm_sec;
00250 
00251 }
00252 
00253 //_____________________________________________________________________________
00254 Int_t VldTimeStamp::GetZoneOffset()
00255 {
00256    // Static method returning local (current) time zone offset from UTC.
00257    // This is the difference in seconds between UTC and local standard time.
00258 
00259    // ?? should tzset (_tzset) be called?
00260 #ifndef R__WIN32
00261    tzset();
00262 #if !defined(R__MACOSX) && !defined(R__FBSD)
00263    return  timezone;   /* unix has extern long int */
00264 #else
00265    time_t *tp = 0;
00266    time(tp);
00267    return localtime(tp)->tm_gmtoff;
00268 #endif
00269 #else
00270    _tzset();
00271    return _timezone;   /* Win32 prepends "_" */
00272 #endif
00273 }
00274 
00275 //_____________________________________________________________________________
00276 void VldTimeStamp::Add(const VldTimeStamp &offset)
00277 {
00278    // Add "offset" as a delta time.
00279 
00280    fSec     += offset.fSec;
00281    fNanoSec += offset.fNanoSec;
00282    NormalizeNanoSec();
00283 
00284 }
00285 
00286 void VldTimeStamp::Add(Double_t seconds)
00287 {
00288   // Add 'seconds' as a delta time
00289 
00290   fSec += (Int_t) seconds;
00291   fNanoSec += (Int_t) (fmod(seconds,1.0) * 1e9);
00292   NormalizeNanoSec();
00293   if(seconds > 1e6) 
00294     MSG("Vld",Msg::kWarning) << "VldTimeStamp moved by offset " << seconds <<" which is too large to maintain ns accuracy." << endl;
00295 }
00296 
00297 //_____________________________________________________________________________
00298 void VldTimeStamp::Print(Option_t *option) const
00299 {
00300    // Print date and time.
00301 
00302    printf("Date/Time = %s\n", AsString(option));
00303 
00304 }
00305 
00306 //_____________________________________________________________________________
00307 void VldTimeStamp::Set()
00308 {
00309    // Set Date/Time to current time as reported by the system.
00310    // no accounting for nanoseconds with std ANSI functions,
00311    // ns part faked so that subsequent calls simply add 1 to it
00312    // this ensures that calls within the same second come back
00313    // distinct (and sortable).
00314 
00315 #ifdef R__WIN32
00316    ULARGE_INTEGER time;
00317    GetSystemTimeAsFileTime((FILETIME *)&time);
00318    // NT keeps time in FILETIME format which is 100ns ticks since
00319    // Jan 1, 1601. TTimeStamps use time in 100ns ticks since Jan 1, 1970.
00320    // The difference is 134774 days.
00321    fNanoSec = Int_t((time.QuadPart * (unsigned __int64) 100) %
00322                     (unsigned __int64) 1000000000);
00323    time.QuadPart -=
00324             (unsigned __int64) (1000*1000*10)       // seconds
00325           * (unsigned __int64) (60 * 60 * 24)       // days
00326           * (unsigned __int64) (134774);            // # of days
00327 
00328    fSec     = Int_t(time.QuadPart/(unsigned __int64) (1000*1000*10));
00329 #else
00330    // this should work on UNIX to get microsec precision
00331    // we'll stick to a ns hack to make calls unique
00332    struct timeval now;
00333    if (!gettimeofday(&now,0)) {
00334       fSec     = now.tv_sec;
00335       fNanoSec = now.tv_usec * 1000;
00336    }
00337    else {
00338       time_t nowtime;
00339       time(&nowtime);
00340       fSec     = nowtime;
00341       fNanoSec = 0;
00342    }
00343 #endif
00344    static Int_t sec = 0, nsec = 0, fake_ns = 0;
00345 
00346    if (fSec == sec && fNanoSec == nsec)
00347       fNanoSec += ++fake_ns;
00348    else {
00349       fake_ns = 0;
00350       sec     = fSec;
00351       nsec    = fNanoSec;
00352    }
00353 
00354 }
00355 
00356 //_____________________________________________________________________________
00357 void VldTimeStamp::Set(Int_t year, Int_t month, Int_t day,
00358                        Int_t hour, Int_t min, Int_t sec, 
00359                        Int_t nsec, Bool_t isUTC, Int_t secOffset)
00360 {
00361    // Set Date/Time from components.
00362    // 
00363    // month & day both use normal 1..12 and 1..31 counting
00364    // hours, min, sec run from 0 to 23, 59, 59 respectively;
00365    // secOffset provides method for adjusting for alternative timezones
00366    //
00367    // "year"  |    0    1 ... 37 | 38...69   |   70 .. 100  101 ..  137
00368    // true    | 2000 2001   2037 | undefined | 1970   2000 2001 .. 2037
00369    //
00370    // "year"  | 138...1969 | 1970 .. 2037 | ...
00371    // true    | undefined  | 1970 .. 2037 | undefined
00372    //
00373 
00374 
00375    // deal with special formats of year
00376    if (year <= 37)                year += 2000;
00377    if (year >= 70 && year <= 137) year += 1900;
00378    // tm.tm_year is years since 1900
00379    if (year >= 1900)              year -= 1900;
00380 
00381    struct tm tmstruct;
00382    tmstruct.tm_year  = year;    // years since 1900
00383    tmstruct.tm_mon   = month-1; // months since Jan [0,11]
00384    tmstruct.tm_mday  = day;     // day of the month [1,31]
00385    tmstruct.tm_hour  = hour;    // hours since midnight [0,23]
00386    tmstruct.tm_min   = min;     // minutes after the hour [0,59]
00387    tmstruct.tm_sec   = sec + secOffset;  // seconds after the minute [0,59]
00388    tmstruct.tm_isdst = -1;     // let "mktime" determine DST setting
00389 
00390    const time_t bad_time_t = (time_t) -1;
00391    // convert tm struct to time_t, if values are given in UTC then
00392    // no standard routine exists and we'll have to use our homegrown routine,
00393    // if values are given in local time then use "mktime"
00394    // which also normalizes the tm struct as a byproduct
00395    time_t utc_sec = (isUTC) ? MktimeFromUTC(&tmstruct) : mktime(&tmstruct);
00396  
00397    //   VldTimeStamp::Dump_tm_struct(tmstruct);
00398 
00399    if (utc_sec == bad_time_t)
00400       MSG("Vld",Msg::kInfo) 
00401          << "VldTimeStamp::Set mktime returned -1" << endl;
00402 
00403    fSec  = utc_sec;
00404    fNanoSec = nsec;
00405 
00406    NormalizeNanoSec();
00407 }
00408 
00409 //_____________________________________________________________________________
00410 void VldTimeStamp::Set(Int_t date, Int_t time, Int_t nsec,
00411                        Bool_t isUTC, Int_t secOffset)
00412 {
00413    // Set date/time from integers of the form [yy]YYMMDD and HHMMSS,
00414    // assume UTC (UTC) components:
00415    //
00416    //  MM: 01=January .. 12=December
00417    //  DD: 01 .. 31
00418    //
00419    //  HH: 00=midnight .. 23
00420    //  MM: 00 .. 59
00421    //  SS: 00 .. 69
00422    //
00423    // Date must be in format 980418 or 19980418
00424    //                       1001127 or 20001127  (i.e. year 100 = 2000).
00425    // Time must be in format 224512 (second precision).
00426    // Date must be >= 700101.
00427 
00428    Int_t year  = date/10000;
00429    Int_t month = (date-year*10000)/100;
00430    Int_t day   = date%100;
00431 
00432    // protect against odd attempts at time offsets
00433    const Int_t oneday = 240000;
00434    while (time < 0) {
00435       time += oneday;
00436       day  -= 1;
00437    }
00438    while (time > oneday) {
00439       time -= oneday;
00440       day  += 1;
00441    }
00442    Int_t hour  = time/10000;
00443    Int_t min   = (time-hour*10000)/100;
00444    Int_t sec   = time%100;
00445 
00446    Set(year, month, day, hour, min, sec, nsec, isUTC, secOffset);
00447 
00448 }
00449 
00450 //_____________________________________________________________________________
00451 void VldTimeStamp::NormalizeNanoSec()
00452 {
00453    // Ensure that the fNanoSec field is in range [0,99999999].
00454 
00455    // deal with negative values
00456    while (fNanoSec < 0) {
00457       fNanoSec += kNsPerSec;
00458       fSec -= 1;
00459    }
00460    // deal with values inf fNanoSec greater than one sec
00461    while (fNanoSec >= kNsPerSec) {
00462       fNanoSec -= kNsPerSec;
00463       fSec += 1;
00464    }
00465 }
00466 //_____________________________________________________________________________
00467 time_t VldTimeStamp::MktimeFromUTC(tm_t *tmstruct)
00468 {
00469    // Equivalent of standard routine "mktime" but
00470    // using the assumption that tm struct is filled with UTC, not local, time.
00471 
00472    // This version *ISN'T* configured to handle every possible
00473    // weirdness of out-of-range values in the case of normalizing
00474    // the tm struct.
00475 
00476    // This version *DOESN'T* correctly handle values that can't be
00477    // fit into a time_t (i.e. beyond year 2038-01-18 19:14:07, or
00478    // before the start of Epoch).
00479 
00480    const Int_t days[]     = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00481    const Int_t daysLeap[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00482 
00483    Int_t year = tmstruct->tm_year + 1900;
00484    Bool_t isleap = VldTimeStamp::IsLeapYear(year);
00485 
00486    const Int_t *daysInMonth = days;
00487    if (isleap) daysInMonth = daysLeap;
00488 
00489    // fill in tmstruct->tm_yday
00490 
00491    int &ref_tm_mon = tmstruct->tm_mon;
00492    int &ref_tm_mday = tmstruct->tm_mday;
00493    // count days in months past
00494    tmstruct->tm_yday = 0;
00495    for (Int_t imonth = 0; imonth < ref_tm_mon; imonth++) {
00496       tmstruct->tm_yday += daysInMonth[imonth];
00497    }
00498    tmstruct->tm_yday += ref_tm_mday - 1;  // day [1-31] but yday [0-365]
00499 
00500    // adjust if day in this month is more than the month has
00501    while (ref_tm_mday > daysInMonth[ref_tm_mon]) {
00502       ref_tm_mday -= daysInMonth[ref_tm_mon];
00503       ref_tm_mon++;
00504    }
00505 
00506    // *should* calculate tm_wday (0-6) here ...
00507 
00508    // UTC is never DST
00509    tmstruct->tm_isdst = 0;
00510 
00511    // Calculate seconds since the Epoch based on formula in
00512    // POSIX  IEEEE Std 1003.1b-1993 pg 22
00513 
00514    Int_t utc_sec = tmstruct->tm_sec +
00515                    tmstruct->tm_min*60 +
00516                    tmstruct->tm_hour*3600 +
00517                    tmstruct->tm_yday*86400 +
00518                    (tmstruct->tm_year-70)*31536000 +
00519                    ((tmstruct->tm_year-69)/4)*86400;
00520 
00521    return utc_sec;
00522 }
00523 
00524 //_____________________________________________________________________________
00525 Bool_t VldTimeStamp::IsLeapYear(Int_t year)
00526 {
00527    // Is the given year a leap year.
00528 
00529 
00530    // The calendar year is 365 days long, unless the year is exactly divisible
00531    // by 4, in which case an extra day is added to February to make the year
00532    // 366 days long. If the year is the last year of a century, eg. 1700, 1800,
00533    // 1900, 2000, then it is only a leap year if it is exactly divisible by
00534    // 400. Therefore, 1900 wasn't a leap year but 2000 was. The reason for
00535    // these rules is to bring the average length of the calendar year into
00536    // line with the length of the Earth's orbit around the Sun, so that the
00537    // seasons always occur during the same months each year.
00538 
00539    if (year%4 != 0) {
00540       return false;
00541    }
00542    else {
00543       if (year%400 == 0) {
00544          return true;
00545       }
00546       else { 
00547          if (year%100 == 0) {
00548             return false;
00549          }
00550          else {
00551             return true;
00552          }
00553       }
00554    }
00555 
00556 }
00557 
00558 //_____________________________________________________________________________
00559 void VldTimeStamp::DumpTMStruct(const tm_t &tmstruct) 
00560 {
00561    // Print out the "tm" structure:
00562    // tmstruct.tm_year = year;    // years since 1900
00563    // tmstruct.tm_mon  = month-1; // months since Jan [0,11]
00564    // tmstruct.tm_mday = day;     // day of the month [1,31]
00565    // tmstruct.tm_hour = hour;    // hours since midnight [0,23]
00566    // tmstruct.tm_min  = min;     // minutes after the hour [0,59]
00567    // tmstruct.tm_sec  = sec;     // seconds after the minute [0,59]
00568    // tmstruct.tm_wday            // day of week [0,6]
00569    // tmstruct.tm_yday            // days in year [0,365]
00570    // tmstruct.tm_isdst           // DST [-1/0/1]  (unknown,false,true)
00571 
00572    printf(" tm { year %4d, mon   %2d, day   %2d,\n",
00573           tmstruct.tm_year,
00574           tmstruct.tm_mon,
00575           tmstruct.tm_mday);
00576    printf("      hour   %2d, min   %2d, sec   %2d,\n",
00577           tmstruct.tm_hour,
00578           tmstruct.tm_min,
00579           tmstruct.tm_sec);
00580    printf("      wday   %2d, yday %3d, isdst %2d",
00581           tmstruct.tm_wday,
00582           tmstruct.tm_yday,
00583           tmstruct.tm_isdst);
00584 #ifdef linux
00585 //#ifdef __GNUC__
00586 // special GCC extras
00587    printf(",\n      tm_gmtoff %7ld,  tm_zone \"%s\"",
00588 #ifdef __USE_BSD
00589           tmstruct.tm_gmtoff,tmstruct.tm_zone);
00590 #else
00591           tmstruct.__tm_gmtoff,tmstruct.__tm_zone);
00592 #endif
00593 #endif
00594    printf("}\n");
00595 }
00596 //_____________________________________________________________________________

Generated on Thu Nov 1 15:54:05 2007 for loon by  doxygen 1.3.9.1