DayTime.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: DayTime.cpp 2960 2011-11-02 05:01:16Z yanweignss $"
00002 
00003 
00004 
00005 //============================================================================
00006 //
00007 //  This file is part of GPSTk, the GPS Toolkit.
00008 //
00009 //  The GPSTk is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU Lesser General Public License as published
00011 //  by the Free Software Foundation; either version 2.1 of the License, or
00012 //  any later version.
00013 //
00014 //  The GPSTk is distributed in the hope that it will be useful,
00015 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 //  GNU Lesser General Public License for more details.
00018 //
00019 //  You should have received a copy of the GNU Lesser General Public
00020 //  License along with GPSTk; if not, write to the Free Software Foundation,
00021 //  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //  
00023 //  Copyright 2004, The University of Texas at Austin
00024 //
00025 //============================================================================
00026 
00027 //============================================================================
00028 //
00029 //This software developed by Applied Research Laboratories at the University of
00030 //Texas at Austin, under contract to an agency or agencies within the U.S. 
00031 //Department of Defense. The U.S. Government retains all rights to use,
00032 //duplicate, distribute, disclose, or release this software. 
00033 //
00034 //Pursuant to DoD Directive 523024 
00035 //
00036 // DISTRIBUTION STATEMENT A: This software has been approved for public 
00037 //                           release, distribution is unlimited.
00038 //
00039 //=============================================================================
00040 
00041 
00042 
00043 
00044 
00045 
00051 #include <iostream>
00052 #include <iomanip>
00053 #include <string>
00054 #include <ctime>
00055 
00056 #include "gpstkplatform.h"
00057 #include "DayTime.hpp"
00058 #include "FormatUtils.hpp"
00059 
00060 namespace gpstk
00061 {
00062    using namespace std;
00063    using namespace gpstk::StringUtils;
00064 
00065       // ----------- Part  0: month and day labels -------------------
00066       //
00068    static const char *MonthNames[] = { 
00069       "Error",
00070       "January","February", "March", "April",
00071       "May", "June","July", "August",
00072       "September", "October", "November", "December"
00073    };
00074   
00076    static const char *MonthAbbrevNames[] = {
00077       "err", "Jan", "Feb", "Mar", "Apr", "May", "Jun","Jul",
00078       "Aug", "Sep", "Oct", "Nov", "Dec"
00079    };
00080   
00082    static const char *DayOfWeekNames[] = {
00083       "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
00084       "Friday", "Saturday"
00085    };
00086 
00088    static const char *DayOfWeekAbbrevNames[] = {
00089       "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
00090    };
00091 
00092       // ----------- Part  1: exceptions and constants ---------------
00093       //
00094 
00095       // mSod is sod*FACTOR and mSec is seconds*FACTOR
00096       // NB FACTOR must be <, and a factor of, 1,000,000
00097    const long DayTime::FACTOR = 1000;
00098 
00099       // Seconds per half a GPS week.
00100    const long DayTime::HALFWEEK = 302400;
00101       // Seconds per whole GPS week.
00102    const long DayTime::FULLWEEK = 604800;
00103       // Seconds per day.
00104    const long DayTime::SEC_DAY = 86400;
00105       // Milliseconds in a day.
00106    const long DayTime::MS_PER_DAY = SEC_DAY*1000;
00107 
00108       // Conversion offset, Julian Date to Modified Julian Date.
00109    const double DayTime::JD_TO_MJD = 2400000.5;
00110       // 'Julian day' offset from MJD
00111    const long DayTime::MJD_JDAY = 2400001L;
00112       // 'Julian day' of GPS epoch (Jan. 1, 1980).
00113    const long DayTime::GPS_EPOCH_JDAY = 2444245L;
00114       // Modified Julian Date of GPS epoch (Jan. 1, 1980).
00115    const long DayTime::GPS_EPOCH_MJD = 44244L;
00116       // Modified Julian Date of UNIX epoch (Jan. 1, 1970).
00117    const long DayTime::UNIX_MJD = 40587L;
00118 
00119       // One nanosecond tolerance.
00120    const double DayTime::ONE_NSEC_TOLERANCE = 1e-9;
00121       // One microsecond tolerance.
00122    const double DayTime::ONE_USEC_TOLERANCE = 1e-6;
00123       // One millisecond tolerance.
00124    const double DayTime::ONE_MSEC_TOLERANCE = 1e-3;
00125       // One second tolerance.
00126    const double DayTime::ONE_SEC_TOLERANCE = 1;
00127       // One minute tolerance.
00128    const double DayTime::ONE_MIN_TOLERANCE = 60;
00129       // One hour tolerance.
00130    const double DayTime::ONE_HOUR_TOLERANCE = 3600;
00131    
00132       // Tolerance for time equality.
00133 #ifdef _WIN32
00134    double DayTime::DAYTIME_TOLERANCE = ONE_USEC_TOLERANCE;
00135 #else
00136    double DayTime::DAYTIME_TOLERANCE = ONE_NSEC_TOLERANCE;
00137 #endif
00138 
00139       // 'julian day' of earliest epoch expressible by DayTime; 1/1/4713 B.C.
00140    const long DayTime::BEGIN_LIMIT_JDAY=0;
00141       // 'julian day' of latest 'julian day' expressible by DayTime, 
00142       // 1/1/4713 A.D.
00143    const long DayTime::END_LIMIT_JDAY=3442448;
00144       // earliest representable DayTime
00145    const DayTime DayTime::BEGINNING_OF_TIME =
00146       DayTime(DayTime::BEGIN_LIMIT_JDAY, 0, 0.0, DayTime::DAYTIME_TOLERANCE);
00147       // latest representable DayTime
00148    const DayTime DayTime::END_OF_TIME =
00149       DayTime(DayTime::END_LIMIT_JDAY, 0, 0.0, DayTime::DAYTIME_TOLERANCE);
00150 
00151       // If true, check the validity of inputs and throw DayTimeException 
00152       //  on failure.
00153    bool DayTime::DAYTIME_TEST_VALID = true;
00154 
00155       // ----------- Part  2: member functions: tolerance -------------
00156       //
00157    DayTime& DayTime::setTolerance(const double tol)
00158       throw()
00159    {
00160       tolerance = tol;
00161       return *this;
00162    }
00163 
00164       // ----------- Part  3: member functions: constructors ----------
00165       //
00166       // Default constructor; initializes to current system time.
00167    DayTime::DayTime()
00168       throw(DayTime::DayTimeException)
00169    {
00170       init();
00171       setSystemTime();
00172    }
00173 
00174       // GPS time with full week constructor.
00175       // @param GPSWeek full week number
00176       // @param GPSSecond seconds of week.
00177       // @param f Time frame (see #TimeFrame)
00178    DayTime::DayTime(short GPSWeek,
00179                     double GPSSecond,
00180                     TimeFrame f)
00181       throw(DayTime::DayTimeException)
00182    {
00183       init();
00184       setGPSfullweek(GPSWeek, GPSSecond, f);
00185    }
00186 
00187       // GPS time constructor.
00188       // @param GPSWeek 10 bit week number.
00189       // @param GPSSecond Seconds of week.
00190       // @param year Four-digit year.
00191       // @param f Time frame (see #TimeFrame)
00192    DayTime::DayTime(short GPSWeek, 
00193                     double GPSSecond,
00194                     short ayear, 
00195                     TimeFrame f)
00196       throw(DayTime::DayTimeException)
00197    {
00198       init();
00199       setGPS(GPSWeek, GPSSecond, ayear, f);
00200    }
00201 
00202       // GPS time constructor.
00203       // @param GPSWeek GPS 10 bit week number.
00204       // @param zcount Z-count (seconds of week / 1.5)
00205       // @param year Four-digit year.
00206       // @param f Time frame (see #TimeFrame)
00207    DayTime::DayTime(short GPSWeek,
00208                     long zcount, 
00209                     short ayear,
00210                     TimeFrame f)
00211       throw(DayTime::DayTimeException)
00212    {
00213       init();
00214       setGPS(GPSWeek, zcount, ayear, f);
00215    }
00216 
00217       // GPS time constructor.
00218       // @param fullZcount Full z-count (3 MSB unused, mid 10 bits -
00219       //   week number, 19 LSB "normal" z-count).
00220       // @param f Time frame (see #TimeFrame)
00221    DayTime::DayTime(unsigned long fullZcount, 
00222                     TimeFrame f)
00223       throw(DayTime::DayTimeException)
00224    {
00225       init();
00226       setGPS(fullZcount, f);
00227    }
00228 
00229       // GPS Zcount constructor.
00230       // @param z GPSZcount object to set to
00231       // @param f Time frame (see #TimeFrame)
00232    DayTime::DayTime(const GPSZcount& z,
00233                     TimeFrame f)
00234       throw(DayTime::DayTimeException)
00235    {
00236       init();
00237       setGPSZcount(z, f);
00238    }
00239 
00240       // CommonTime constructor.
00241       // @param c CommonTime object to set to
00242       // @param f Time frame (see #TimeFrame)
00243    DayTime::DayTime(const CommonTime& c,
00244                     TimeFrame f)
00245       throw(DayTime::DayTimeException)
00246    {
00247       init();
00248       setCommonTime(c, f);
00249    }   
00250    
00251       // Calendar time constructor.
00252       // @param yy four-digit year.
00253       // @param mm month of year (1-based).
00254       // @param dd day of month (1-based).
00255       // @param hh hour of day.
00256       // @param min minutes of hour.
00257       // @param sec seconds of minute.
00258       // @param f Time frame (see #TimeFrame)
00259    DayTime::DayTime(short yy, 
00260                     short mm,
00261                     short dd,
00262                     short hh, 
00263                     short min, 
00264                     double sec, 
00265                     TimeFrame f)
00266       throw(DayTime::DayTimeException)
00267    {
00268       init();
00269       setYMDHMS(yy, mm, dd, hh, min, sec, f);
00270    }
00271 
00272       // Modified Julian date time constructor.
00273       // @param julian Modified Julian date.
00274       // @param f Time frame (see #TimeFrame)
00275    DayTime::DayTime(long double mjd,
00276                     TimeFrame f)
00277       throw(DayTime::DayTimeException)
00278    {
00279       init();
00280       setMJD(mjd, f);
00281    }
00282 
00283       // Modified Julian date time constructor.
00284       // @param MJD Modified Julian date as double.
00285       // @param f Time frame (see #TimeFrame)
00286    DayTime::DayTime(double mjd, 
00287                     TimeFrame f)
00288       throw(DayTime::DayTimeException)
00289    {
00290       init();
00291       setMJD((long double)(mjd), f);
00292    }
00293 
00294       // Day of year time constructor.
00295       // @param year Four-digit year.
00296       // @param DOY Day of year.
00297       // @param SOD Seconds of day.
00298       // @param f Time frame (see #TimeFrame)
00299    DayTime::DayTime(short year, 
00300                     short doy, 
00301                     double sod,
00302                     TimeFrame f)
00303       throw(DayTime::DayTimeException)
00304    {
00305       init();
00306       setYDoySod(year,doy,sod,f);
00307    }
00308 
00309       // UNIX time constructor.
00310       // @param t timeval structure (typically from gettimeofday()).
00311       // @param f Time frame (see #TimeFrame)
00312    DayTime::DayTime(const struct timeval& t, 
00313                     TimeFrame f)
00314       throw(DayTime::DayTimeException)
00315    {
00316       init();
00317       setUnix(t,f);
00318       timeFrame = f;
00319    }
00320 
00321       // ----------- Part  4: member functions: assignment and copy ----------
00322       //
00323       // Copy constructor
00324    DayTime::DayTime(const DayTime &right)
00325       throw(DayTime::DayTimeException)
00326    {
00327       init();
00328       *this = right;
00329    }
00330 
00331       // Assignment operator.
00332    DayTime& DayTime::operator=(const DayTime& right)
00333       throw()
00334    {
00335       jday = right.jday;
00336       mSod = right.mSod;
00337       mSec = right.mSec;
00338       timeFrame  = right.timeFrame;
00339       tolerance  = right.tolerance;
00340       return *this;
00341    }
00342 
00343       // ----------- Part  5: member functions: arithmetic ------------
00344       //
00345       // DayTime difference function.
00346       // @param right DayTime to subtract from this one.
00347       // @return difference in seconds.
00348    double DayTime::operator-(const DayTime& right) const
00349       throw()
00350    {
00351       return ( SEC_DAY * double(jday - right.jday)
00352             + (double(mSod - right.mSod) + mSec - right.mSec) / FACTOR );
00353    }
00354 
00355       // Add seconds to this time.
00356       // @param seconds Number of seconds to increase this time by.
00357       // @return The new time incremented by \c seconds.
00358    DayTime DayTime::operator+(double seconds) const
00359       throw()
00360    {
00361       return DayTime(*this).addSeconds(seconds);
00362    }
00363 
00364       // Subtract seconds from this time.
00365       // @param seconds Number of seconds to decrease this time by.
00366       // @return The new time decremented by \c seconds.
00367    DayTime DayTime::operator-(double seconds) const
00368       throw()
00369    {
00370       return DayTime(*this).addSeconds(-seconds);
00371    }
00372 
00373       // Add seconds to this time.
00374       // @param seconds Number of seconds to increase this time by.
00375    DayTime& DayTime::operator+=(double seconds)
00376       throw(DayTime::DayTimeException)
00377    {
00378       addSeconds(seconds);
00379       return *this;
00380    }
00381    
00382       // Subtract seconds from this time.
00383       // @param sec Number of seconds to decrease this time by.
00384    DayTime& DayTime::operator-=(double seconds)
00385       throw(DayTime::DayTimeException)
00386    {
00387       addSeconds(-seconds);
00388       return *this;
00389    }
00390 
00391       // Add seconds to this object.
00392       // @param seconds Number of seconds to add
00393    DayTime& DayTime::addSeconds(double seconds)
00394       throw(DayTime::DayTimeException)
00395    {
00396       addLongDeltaTime(0, 0, seconds * FACTOR);
00397       return *this;
00398    }
00399 
00400       // Add (integer) seconds to this object.
00401       // @param seconds Number of seconds to add.
00402    DayTime& DayTime::addSeconds(long seconds)
00403       throw(DayTime::DayTimeException)
00404    {
00405       long ldd, lds ;
00406       ldd = seconds / SEC_DAY ;        // days
00407       seconds %= SEC_DAY ;             // seconds-of-day
00408       lds = seconds * FACTOR ;
00409       addLongDeltaTime(ldd, lds, 0) ;
00410       return *this ;
00411    }
00412 
00413       // Add (integer) milliseconds to this object.
00414       // @param msec Number of milliseconds to add.
00415    DayTime& DayTime::addMilliSeconds(long msec)
00416       throw(DayTime::DayTimeException)
00417    {
00418       long ldd, lds ;
00419       ldd = msec / MS_PER_DAY ;        // days
00420       msec %= MS_PER_DAY ;             // milliseconds-of-day
00421       lds = msec * FACTOR / 1000 ;
00422       addLongDeltaTime(ldd, lds, 0) ;
00423       return *this;
00424    }
00425 
00426       // Add (integer) microseconds to this object.
00427       // @param usec Number of microseconds to add.
00428    DayTime& DayTime::addMicroSeconds(long usec)
00429       throw(DayTime::DayTimeException)
00430    {
00431          // NB FACTOR must be <, and a factor of, 1000000 :
00432       long ldd, lds, mult = (1000000 / FACTOR);
00433       double ds;
00434       ldd = usec / (1000000ll * SEC_DAY);        // days
00435       usec %= (1000000ll * SEC_DAY);             // usec-of-day
00436       lds = usec / mult;                        // long sec/FACTOR's
00437       ds = double(usec % mult) / mult;          // frac sec/FACTOR's
00438       addLongDeltaTime(ldd, lds, ds);
00439       return *this;
00440    }
00441 
00442       // ----------- Part  6: member functions: comparisons ------------
00443       //
00444       // Equality operator.
00445    bool DayTime::operator==(const DayTime &right) const 
00446       throw()
00447    {
00448       // use the smaller of the two tolerances for comparison
00449       return (ABS(operator-(right)) <=
00450          ((tolerance > right.tolerance) ? right.tolerance : tolerance));
00451    }
00452       // Inequality operator.
00453    bool DayTime::operator!=(const DayTime &right) const 
00454       throw()
00455    {
00456       return !(operator==(right));
00457    }
00458       // Comparison operator (less-than).
00459    bool DayTime::operator<(const DayTime &right) const 
00460       throw()
00461    {
00462       return (operator-(right) <
00463             -((tolerance > right.tolerance) ? right.tolerance : tolerance));
00464    }
00465       // Comparison operator (greater-than).
00466    bool DayTime::operator>(const DayTime &right) const 
00467       throw()
00468    {
00469       return (operator-(right) >
00470             ((tolerance > right.tolerance) ? right.tolerance : tolerance));
00471    }
00472       // Comparison operator (less-than or equal-to).
00473    bool DayTime::operator<=(const DayTime &right) const 
00474       throw()
00475    {
00476       return !(operator>(right));
00477    }
00478       // Comparison operator (greater-than or equal-to).
00479    bool DayTime::operator>=(const DayTime &right) const 
00480       throw()
00481    {
00482       return !(operator<(right));
00483    }
00484 
00485    // ----------- Part  7: member functions: time frame-----------------------
00486    //
00487    DayTime& DayTime::setAllButTimeFrame(const DayTime& right)
00488       throw(DayTime::DayTimeException)
00489    {
00490       TimeFrame t = timeFrame;
00491       *this = right;
00492       timeFrame = t;
00493       return *this;
00494    }
00495 
00496    // ----------- Part  8: member functions: get -----------------------------
00497    //
00498    // 
00499    // These routines let you retrieve the time stored in this object.
00500    //
00501       // Get Julian Date JD
00502    double DayTime::JD() const throw()
00503    {
00504       return (double(jday) + secOfDay() / SEC_DAY - 0.5);
00505    }
00506 
00507       // Get Modified Julian Date MJD
00508    double DayTime::MJD() const
00509       throw()
00510    {
00511       return JD() - JD_TO_MJD ;
00512    }
00513 
00514       // Get year.
00515    short DayTime::year() const 
00516       throw()
00517    {
00518       int yy, mm, dd;
00519       convertJDtoCalendar(jday, yy, mm, dd);
00520       return yy;
00521    }
00522 
00523       // Get month of year.
00524    short DayTime::month() const 
00525       throw()
00526    {
00527       int yy, mm, dd;
00528       convertJDtoCalendar(jday, yy, mm, dd);
00529       return mm;
00530    }
00531 
00532       // Get day of month.
00533    short DayTime::day() const
00534       throw()
00535    {
00536       int yy,mm,dd;
00537       convertJDtoCalendar(jday, yy, mm, dd);
00538       return dd;
00539    }
00540 
00541       // Get day of week
00542    short DayTime::dayOfWeek() const 
00543       throw()
00544    {
00545       return (((jday % 7) + 1) % 7) ;
00546    }
00547 
00548       // Get hour of day.
00549    short DayTime::hour() const
00550       throw()
00551    {
00552       int hh, mm ;
00553       double sec ; 
00554       convertSODtoTime(secOfDay(), hh, mm, sec);
00555       return hh;
00556    }
00557 
00558       // Get minutes of hour.
00559    short DayTime::minute() const
00560       throw()
00561    {
00562       int hh, mm ;
00563       double sec ;
00564       convertSODtoTime(secOfDay(), hh, mm, sec);
00565       return mm;
00566    }
00567 
00568       // Get seconds of minute.
00569    double DayTime::second() const
00570       throw()
00571    {
00572       int hh, mm ;
00573       double sec ;
00574       convertSODtoTime(secOfDay(), hh, mm, sec) ;
00575       return sec;
00576    }
00577 
00578       // Get 10-bit GPS week.
00579    short DayTime::GPS10bitweek() const 
00580       throw()
00581    {
00582       return (GPSfullweek() % 1024); 
00583    }
00584 
00585       // Get normal (19 bit) zcount.
00586    long DayTime::GPSzcount() const 
00587       throw()
00588    {
00589       return (long)((GPSsow() / 1.5) + .5);
00590    }
00591 
00592       // Same as GPSzcount() but without rounding to nearest zcount.
00593    long DayTime::GPSzcountFloor() const
00594       throw()
00595    {
00596       return (long)(GPSsow() / 1.5);
00597    }
00598 
00599       // Get seconds of week.
00600    double DayTime::GPSsow() const
00601       throw()
00602    {
00603       return double(GPSday() * SEC_DAY) + secOfDay() ;
00604    }
00605 
00606       // Get full (>10 bits) week 
00607    short DayTime::GPSfullweek() const
00608       throw()
00609    {
00610       return short(double(jday - GPS_EPOCH_JDAY) / 7) ;
00611    }
00612 
00613       // Get day of year.
00614    short DayTime::DOY() const 
00615       throw()
00616    {
00617       int yy, mm, dd;
00618       convertJDtoCalendar(jday, yy, mm, dd);
00619       return (jday - convertCalendarToJD(yy, 1, 1) + 1) ;
00620    }
00621 
00622       // Get object time as a modified Julian date.
00623    long double DayTime::getMJDasLongDouble() const
00624       throw()
00625    {
00626       return ( (long double)(jday)
00627                + (long double)(secOfDay() / SEC_DAY - 0.5)
00628                - (long double)(JD_TO_MJD) );
00629    }
00630 
00631       // Get object time in UNIX timeval structure.
00632    struct timeval DayTime::unixTime() const
00633       throw(DayTime::DayTimeException)
00634    {
00635       struct timeval t;
00636 
00637       t.tv_sec = mSod / FACTOR 
00638          + long(jday - MJD_JDAY - UNIX_MJD) * SEC_DAY ;
00639 
00640       t.tv_usec = (mSod % FACTOR) * (1000000 / FACTOR)
00641          + long(mSec * (1000000 / FACTOR) + 0.5) ;
00642 
00643       if (t.tv_usec >= 1000000) 
00644       {
00645          t.tv_usec -= 1000000; 
00646          ++t.tv_sec; 
00647       }
00648 
00649       return t;
00650    }
00651 
00652       // Get time as 32 bit Z count.
00653       // The 13 MSBs are week modulo 1024, 19 LSBs are seconds of
00654       // week in Zcounts.
00655    unsigned long DayTime::fullZcount() const
00656       throw()
00657    {
00658       return ((long(GPS10bitweek()) << 19) + GPSzcount()) ;
00659    }
00660 
00661       // Same as fullZcount() but without rounding to nearest zcount.
00662    unsigned long DayTime::fullZcountFloor() const
00663       throw()
00664    {
00665       return ((long(GPS10bitweek()) << 19) + GPSzcountFloor()) ;
00666    }
00667 
00668    DayTime::operator GPSZcount() const
00669       throw(DayTime::DayTimeException)
00670    {
00671       try
00672       {
00673             // account for rounding error in GPSzcount()
00674          if(GPSzcount() == GPSZcount::ZCOUNT_WEEK)
00675          {
00676             return GPSZcount(GPSfullweek() + 1, 0);
00677          }
00678          else
00679          {
00680             return GPSZcount(GPSfullweek(), GPSzcount());
00681          }
00682       }
00683       catch (gpstk::InvalidParameter& ip)
00684       {
00685          DayTime::DayTimeException de(ip);
00686          GPSTK_THROW(de);
00687       }
00688    }
00689 
00690    DayTime::operator CommonTime() const
00691       throw(DayTime::DayTimeException)
00692    {
00693       try
00694       {
00695             // Multiply by 1/FACTOR to convert mSec from milliseconds to seconds.
00696          return CommonTime().setInternal(jday, mSod, mSec / FACTOR);
00697       }
00698       catch (gpstk::InvalidParameter& ip)
00699       {
00700          DayTime::DayTimeException de(ip);
00701          GPSTK_THROW(de);
00702       }
00703    }
00704 
00705       // ----------- Part  9: member functions: set -------------
00706       //
00707       // Set the object's time using calendar (Y/M/D) date and ordinary (H:M:S)
00708       //  time.
00709       // @param yy four-digit year.
00710       // @param month month of year (1-based).
00711       // @param day day of month (1-based).
00712       // @param hour hour of day.
00713       // @param min minutes of hour.
00714       // @param sec seconds of minute.
00715       // @param f Time frame (see #TimeFrame)
00716       // @return a reference to this object.
00717    DayTime& DayTime::setYMDHMS(short yy,
00718                                short month, 
00719                                short day, 
00720                                short hour,
00721                                short min, 
00722                                double sec,
00723                                TimeFrame f)
00724       throw(DayTime::DayTimeException)
00725    {
00726       setYMD(yy, month, day, f);
00727       return setHMS(hour, min, sec, f);
00728    }
00729 
00730       // Set the object time using GPS time. If the GPS week is
00731       // 10 bit, the full week is determined from the system clock.
00732       // @param week Week number (can be 10 bit).
00733       // @param sow Seconds of week.
00734       // @param f Time frame (see #TimeFrame)
00735       // @return a reference to this object.
00736    DayTime& DayTime::setGPS(short week, 
00737                             double sow, 
00738                             TimeFrame f)
00739       throw(DayTime::DayTimeException)
00740    {
00741       short fullweek=week;
00742       if(week < 1024) {
00743          DayTime ndt;
00744          ndt.setSystemTime();
00745          fullweek = 1024*(ndt.GPSfullweek()/1024) + week;
00746       }
00747       return setGPSfullweek(fullweek,sow,f);
00748    }
00749 
00750       // Set the object's time using GPS time. If the GPS week
00751       // is 10 bit, the full week is determined from the system clock.
00752       // @param week GPS 10 bit week number.
00753       // @param zcount Z-count (seconds of week / 1.5)
00754       // @param f Time frame (see #TimeFrame)
00755       // @return a reference to this object.
00756    DayTime& DayTime::setGPS(short week,
00757                             long zcount, 
00758                             TimeFrame f)
00759       throw(DayTime::DayTimeException)
00760    {
00761       return setGPS(week, double(zcount) * 1.5, f);
00762    }
00763 
00764       // Set the object's time using GPS time.
00765       // @param week GPS 10 bit week number.
00766       // @param zcount Z-count (seconds of week / 1.5)
00767       // @param year Four-digit year.
00768       // @param f Time frame (see #TimeFrame)
00769       // @return a reference to this object.
00770    DayTime& DayTime::setGPS(short week,
00771                             long zcount,
00772                             short year,
00773                             TimeFrame f)
00774       throw(DayTime::DayTimeException)
00775    {
00776       return setGPS(week, double(zcount) * 1.5, year, f);
00777    }
00778 
00779       // Set the object's time using input GPS 10-bit
00780       // week and seconds of week; determine the number
00781       // of GPS week rollovers by deducing it from the input year and week.
00782       // @param week 10 bit week number.
00783       // @param sow Seconds of week.
00784       // @param year Four-digit year.
00785       // @param f Time frame (see #TimeFrame)
00786       // @return a reference to this object.
00787    DayTime& DayTime::setGPS(short week, 
00788                             double sow, 
00789                             short year,
00790                             TimeFrame f)
00791       throw(DayTime::DayTimeException)
00792    {
00793       bool valid = true;
00794 
00795       if (DAYTIME_TEST_VALID)
00796       {
00797          if ((year < 1980) || (week < 0))
00798             valid = false;
00799       }
00800       
00801       if (valid)
00802       {
00803          DayTime dt;
00804 
00805             // In case the user supplies the full GPS week number.
00806          week %= 1024;
00807          
00808          dt.setYMD(year, 1, 1);
00809             // z1 is the number of GPS 10-bit-week roll-overs at the beginning
00810             //  of the year.
00811          short z1 = dt.GPSfullweek() / 1024;
00812 
00813          dt.setYMD(year, 12, 31);
00814             // z2 is the number of GPS 10-bit-week roll-overs at the end
00815             //  of the year.
00816          short z2 = dt.GPSfullweek() / 1024;
00817 
00818             // GPS 10-bit-week *does not* roll-over during the year.
00819          if (z1 == z2) 
00820          {
00821             return setGPSfullweek(week + z1 * 1024, sow, f);
00822          }
00823             // GPS 10-bit-week *does* roll-over during the year.
00824          else
00825          {
00826             if (week <= 512)  // roll-over happened before week ... use z2
00827             {
00828                return setGPSfullweek(week + z2 * 1024, sow, f);
00829             }
00830             else if (week > 512)  // roll-over happened after week ... use z1
00831             {
00832                return setGPSfullweek(week + z1 * 1024, sow, f);
00833             }
00834          }
00835       }
00836 
00837          // If we get here, valid is false.
00838       if(DAYTIME_TEST_VALID)
00839       {
00840          using gpstk::StringUtils::asString ;
00841          DayTimeException dte("Input inconsistent: year "
00842                               + asString<int>(year)
00843                               + " cannot contain 10-bit GPS week "
00844                               + asString<short>(week));
00845          GPSTK_THROW(dte);
00846       }
00847 
00848       return *this;
00849    }
00850 
00851       // Set the object's time using GPS time. System time
00852       // is used to determine which 'zone' of 1024 weeks is assigned.
00853       // @param Zcount Full z-count (3 MSB unused, mid 10 bits -
00854       //   week number, 19 LSB "normal" z-count).
00855       // @param f Time frame (see #TimeFrame)
00856       // @return a reference to this object.
00857    DayTime& DayTime::setGPS(unsigned long Zcount, 
00858                             TimeFrame f)
00859       throw(DayTime::DayTimeException)
00860    {
00861       short cweek = (Zcount >> 19) & 0x3FF ;
00862       long zcount = Zcount & 0x7FFFFL ;
00863       if(DAYTIME_TEST_VALID) 
00864       {
00865          if(cweek < 0 || cweek > 1023 ||    // Is this is a necessary check?
00866             zcount < 0 || zcount > 403199 ) 
00867          { 
00868             using gpstk::StringUtils::asString ;
00869             DayTimeException dte("Invalid Full GPS Z-count: "
00870                                  + asString<unsigned long>(Zcount));
00871             GPSTK_THROW(dte);
00872          }
00873       }
00874       return setGPS(cweek, zcount, f);
00875    }
00876 
00877       // Set the object's time using GPS time.
00878       // @param fullweek Full (i.e. >10bits) GPS week number.
00879       // @param sow Seconds of week.
00880       // @param f Time frame (see #TimeFrame)
00881       // @return a reference to this object.
00882    DayTime& DayTime::setGPSfullweek(short fullweek,
00883                                     double sow, 
00884                                     TimeFrame f)
00885       throw(DayTime::DayTimeException)
00886    {
00887       if(DAYTIME_TEST_VALID) 
00888       {
00889          if(fullweek < 0 || 
00890             sow < 0.0 || 
00891             sow >= double(FULLWEEK))
00892          {
00893             using gpstk::StringUtils::asString ;
00894             DayTimeException dte("Invalid week/seconds-of-week: " 
00895                                  + asString<short>(fullweek)+ "/" 
00896                                  + asString(sow));
00897             GPSTK_THROW(dte);
00898          }
00899       }
00900       jday = GPS_EPOCH_JDAY + 7 * long(fullweek) + long(sow / SEC_DAY);
00901       double sod = sow - SEC_DAY * long(sow / SEC_DAY);
00902       return setSecOfDay(sod, f);
00903    }
00904 
00905       // Set the object's time using the given GPSZcount.
00906       // System time is used to disambiguate which 1024 week 'zone'
00907       // is appropriate.
00908       // @param z the GPSZcount object to set to
00909       // @param f Time frame (see #TimeFrame)
00910       // @return a reference to this object.
00911    DayTime& DayTime::setGPSZcount(const GPSZcount& z,
00912                                   TimeFrame f)
00913       throw(DayTime::DayTimeException)
00914    {
00915       setGPS(z.getWeek(), z.getZcount(), f) ;
00916       return *this ;
00917    }
00918 
00919       // Set the object's time using the give CommonTime.
00920       // @param c the CommonTime object to set to
00921       // @param f Time frame (see #TimeFrame))
00922       // @return a reference to this object.
00923    DayTime& DayTime::setCommonTime(const CommonTime& c,
00924                                    TimeFrame f)
00925       throw()
00926    {
00927       c.get(jday, mSod, mSec);
00928          // Convert mSec from seconds to milliseconds by multiplying by 1000.
00929       mSec *= FACTOR;
00930       timeFrame = f;
00931       return *this;
00932    }
00933    
00934       // Set the object's time using day of year.
00935       // @param year Four-digit year.
00936       // @param day_of_year Day of year.
00937       // @param sec_of_day Seconds of day.
00938       // @param f Time frame (see #TimeFrame)
00939       // @return a reference to this object.
00940    DayTime& DayTime::setYDoySod(short year, 
00941                                 short doy,
00942                                 double sod,
00943                                 TimeFrame f)
00944       throw(DayTime::DayTimeException)
00945    {
00946       setYDoy(year, doy, f);
00947       return setSecOfDay(sod, f);
00948    }
00949 
00950       // Set the object's time using Modified Julian date.
00951       // This just sets the time to the indicated modified Julian date.
00952       // @param mjd the MJD of the date & time to set
00953       // @param f Time frame (see #TimeFrame)
00954       // @return a reference to this object.
00955    DayTime& DayTime::setMJD(long double mjd,
00956                             TimeFrame f)
00957       throw(DayTime::DayTimeException)
00958    {
00959       if(DAYTIME_TEST_VALID) 
00960       {
00961          if(mjd < (long double)(BEGIN_LIMIT_JDAY-MJD_JDAY) ||
00962             mjd > (long double)(END_LIMIT_JDAY-MJD_JDAY))
00963          {
00964             DayTimeException dte("Invalid MJD: " 
00965                                  + gpstk::StringUtils::asString(mjd)) ;
00966             GPSTK_THROW(dte) ;
00967          }
00968       }
00969       jday = long(mjd + 1.0) ;       // int part of JD contributed by MJD
00970       long double sod = SEC_DAY * (mjd + 1.0 - double(jday)) ;
00971       jday += MJD_JDAY - 1 ; 
00972       mSod = long(FACTOR * sod) ;
00973       mSec = FACTOR * double(sod) - double(mSod) ;
00974       realignInternals();
00975       timeFrame = f ;
00976       return *this ;
00977    }
00978 
00979       // set using unix timeval struct
00980    DayTime& DayTime::setUnix(const struct timeval& t,
00981                              TimeFrame f)
00982       throw(DayTime::DayTimeException)
00983    {
00984       long sec = t.tv_sec ;
00985       double dt = double(sec) + (t.tv_usec * 1.e-6) ;
00986       jday = MJD_JDAY + UNIX_MJD + long(dt / SEC_DAY) ;
00987       sec -= long(dt / SEC_DAY) * SEC_DAY ;
00988       dt = double(sec) + (t.tv_usec * 1.e-6) ;
00989       return setSecOfDay(dt);
00990    }
00991 
00992       // set using ANSI
00993    DayTime& DayTime::setANSI(const time_t& t, 
00994                              TimeFrame f)
00995       throw(DayTime::DayTimeException)
00996    {
00997       long double dt = (long double)(t);
00998       dt /= SEC_DAY;
00999       dt += UNIX_MJD;
01000       return setMJD(dt, f);
01001    }
01002 
01003       // set using system time
01004    DayTime& DayTime::setSystemTime()
01005       throw(DayTime::DayTimeException)
01006    {
01007 #if defined(ANSI_ONLY)
01008       time_t t;
01009       time(&t);
01010       setANSI(t, LocalSystem);
01011 #elif defined(WIN32)
01012       _timeb t;
01013       _ftime(&t);
01014       timeval tv;
01015       tv.tv_sec = t.time;
01016       tv.tv_usec = t.millitm*1000;
01017       setUnix(tv, LocalSystem);
01018 #else
01019       timeval t;
01020       gettimeofday(&t, NULL);
01021       setUnix(t, LocalSystem);
01022 #endif
01023       return *this;
01024    }
01025 
01026       // set using local time
01027    DayTime& DayTime::setLocalTime()
01028       throw(DayTime::DayTimeException)
01029    {
01030       time_t t;
01031       time(&t);
01032       struct tm  *ltod;
01033       ltod = localtime(&t);
01034       setYMDHMS(1900 + ltod->tm_year, ltod->tm_mon + 1, ltod->tm_mday,
01035          ltod->tm_hour, ltod->tm_min, ltod->tm_sec);
01036       return *this;
01037    }
01038 
01039       // end of set...() that set Day and Time
01040       // add set...() that set only Day or only Time
01041       //
01042       // Set the object using calendar (Y/M/D) date only (time is unchanged)
01043    DayTime& DayTime::setYMD(int yy, 
01044                             int mm, 
01045                             int dd, 
01046                             TimeFrame f)
01047       throw(DayTime::DayTimeException)
01048    {
01049       long tempDay = convertCalendarToJD(yy, mm, dd);
01050       if(DAYTIME_TEST_VALID) 
01051       {
01052          int y, m, d;
01053          convertJDtoCalendar(tempDay, y, m, d);
01054          if(y != yy || m != mm || d != dd) 
01055          {
01056             using gpstk::StringUtils::asString ;
01057             DayTimeException dte("Invalid yy/mm/dd: " + asString<int>(yy) + "/"
01058                                  + asString<int>(mm) + "/" + asString<int>(dd)
01059                                  + " != " + asString<int>(y) + "/"
01060                                  + asString<int>(m) + "/" + asString<int>(d));
01061             GPSTK_THROW(dte);
01062          }
01063       }
01064       jday = tempDay;
01065       timeFrame = f;
01066       return *this;
01067    }
01068 
01069       // Set the object using ordinary (H:M:S) time only (day is unchanged)
01070    DayTime& DayTime::setHMS(int hh,
01071                             int mm,
01072                             double sec,
01073                             TimeFrame f)
01074       throw(DayTime::DayTimeException)
01075    {
01076       double sod = convertTimeToSOD(hh, mm, sec);
01077       if(DAYTIME_TEST_VALID) 
01078       {
01079          int h, m;
01080          double s;
01081          convertSODtoTime(sod, h, m, s);
01082          if(h != hh || m != mm || ABS(s - sec) > tolerance) 
01083          {
01084             using gpstk::StringUtils::asString ;
01085             DayTimeException dte("Invalid hh:mm:ss: " + asString<int>(hh)
01086                                  + ":" + asString<int>(mm) 
01087                                  + ":" + asString(sec));
01088             GPSTK_THROW(dte);
01089          }
01090       }
01091       return setSecOfDay(sod,f);
01092    }
01093 
01094       // Set the object using seconds of day only (day is unchanged)
01095    DayTime& DayTime::setSecOfDay(double sod, 
01096                                  TimeFrame f)
01097       throw(DayTime::DayTimeException)
01098    {
01099       if(DAYTIME_TEST_VALID) 
01100       {
01101          if(sod < 0.0 || sod >= double(SEC_DAY)) 
01102          {
01103             DayTimeException dte("Invalid seconds-of-day: " 
01104                                  + gpstk::StringUtils::asString(sod));
01105             GPSTK_THROW(dte);
01106          }
01107       }
01108       mSod = long(FACTOR * sod);
01109       mSec = FACTOR * sod - double(mSod);
01110       realignInternals();
01111       timeFrame = f;
01112       return *this;
01113    }
01114 
01115       // Set the object using year and day of year only (time is unchanged)
01116    DayTime& DayTime::setYDoy(int yy,
01117                              int doy,
01118                              TimeFrame f)
01119       throw(DayTime::DayTimeException)
01120    {
01121       jday = convertCalendarToJD(yy, 1, 1) + doy - 1;
01122       if(DAYTIME_TEST_VALID)
01123       {
01124          int y,m,d;
01125          convertJDtoCalendar(jday, y, m, d);
01126          if(y != yy) 
01127          {
01128             DayTimeException dte("Invalid Year/Day-of-Year: " 
01129                                  + gpstk::StringUtils::asString(yy)
01130                                  + "/" + gpstk::StringUtils::asString(doy));
01131             GPSTK_THROW(dte);
01132          }
01133       }
01134       timeFrame = f;
01135       return *this;
01136    }
01137 
01138       // ----------- Part 10: member functions: setToString, printf ---------
01139       //
01140    DayTime& DayTime::setToString(const string& str,
01141                                  const string& fmt)
01142       throw(DayTime::DayTimeException, DayTime::FormatException,
01143             StringException)
01144    {
01145       try
01146       {
01147             // make an object to return
01148          DayTime toReturn(*this);
01149          
01150             // test completeness of specification given by input
01151          bool hmjd = false, hsow = false, hweek = false, hfullWeek = false,
01152             hdow = false, hyear = false, hmonth = false, hday= false,
01153             hzcount = false, hdoy = false, hfullzcount = false,
01154             hhour = false, hmin = false, hsec = false, hsod = false,
01155             hunixsec = false, hunixusec = false;
01156 
01157          double imjd, isow;
01158          short iweek, ifullWeek, idow, imonth, iday;
01159          long izcount, idoy;
01160          long ifullzcount;
01161          
01162          short iyear, ihour, imin;
01163          double isec, isod;
01164          
01165             // unix time
01166          long unixsec, unixusec;
01167          
01168             // set the year in case it is not in the input -- for week input
01169          iyear = toReturn.year();
01170 
01171          string f = fmt;
01172          string s = str;
01173          
01174             // parse strings...  As we process each part, it's removed from 
01175             // both strings so when we reach 0, we're done
01176          while ( (s.size() > 0) && (f.size() > 0) )
01177          {
01178                // remove everything in f and s up to the first % in f
01179                // (these parts of the strings must be identical or this will 
01180                // break after it tries to remove it!)
01181             while ( (s.length() != 0) && (f.length() != 0) && (f[0] != '%') )
01182             {
01183                   // remove that character now and other whitespace
01184                s.erase(0,1);
01185                f.erase(0,1);
01186             }
01187             
01188                // check just in case we hit the end of either string...
01189             if ( (s.length() == 0) || (f.length() == 0) )
01190                break;
01191             
01192                // lose the '%' in f...
01193             f.erase(0,1);
01194             
01195             // if the format string is like %03f, get '3' as the field length.
01196             string::size_type fieldLength = string::npos;
01197             
01198             if (!isalpha(f[0]))
01199             {
01200                // This is where we have a specified field length so we should
01201                // not throw away any more characters
01202                fieldLength = asInt(f);
01203                
01204                // remove everything else up to the next character
01205                // (in "%03f", that would be 'f')
01206                while ((!f.empty()) && (!isalpha(f[0])))
01207                   f.erase(0,1);
01208                if (f.empty())
01209                   break;
01210             }
01211             else
01212             {
01213                // finally, get the character that should end this field, if any
01214                char delimiter = 0;
01215                if (f.size() > 1)
01216                {
01217                   if (f[1] != '%')
01218                   {
01219                      delimiter = f[1];
01220                      
01221                      stripLeading(s);
01222                      fieldLength = s.find(delimiter,0);
01223                   }
01224 
01225                   // if the there is no delimiter character and the next field
01226                   // is another part of the time to parse, assume the length
01227                   // of this field is 1
01228                   else if (fieldLength == string::npos)
01229                   {
01230                      fieldLength = 1;
01231                   }
01232                }
01233             }
01234 
01235             // figure out the next string to be removed.  if there is a
01236             // field length, use that first
01237             string toBeRemoved = s.substr(0, fieldLength);
01238             
01239             // based on char at f[0], convert input to temporary variable
01240             switch (f[0]) 
01241             {
01242                case 'Q':
01243                {
01244                   imjd = asDouble(toBeRemoved);
01245                   hmjd = true;
01246                }
01247                break;
01248 
01249                case 'Z':
01250                {
01251                   izcount = asInt(toBeRemoved);
01252                   hzcount = true;
01253                }
01254                break;
01255 
01256                case 's':
01257                {
01258                   isod = asDouble(toBeRemoved);
01259                   hsod = true;
01260                }
01261                break;
01262 
01263                case 'g':
01264                {
01265                   isow = asDouble(toBeRemoved);
01266                   hsow = true;
01267                }
01268                break;
01269 
01270                case 'w':
01271                {
01272                   idow = asInt(toBeRemoved);
01273                   hdow = true;
01274                }
01275                break;
01276 
01277                case 'G':
01278                {
01279                   iweek = asInt(toBeRemoved);
01280                   hweek = true;
01281                }
01282                break;
01283 
01284                case 'F':
01285                {
01286                   ifullWeek = asInt(toBeRemoved);
01287                   hfullWeek = true;
01288                }
01289                break;
01290 
01291                case 'j':
01292                {
01293                   idoy = asInt(toBeRemoved);
01294                   hdoy = true;
01295                }
01296                break;
01297 
01298                case 'b':
01299                case 'B':
01300                {
01301                   string thisMonth(toBeRemoved);
01302                   lowerCase(thisMonth);
01303                   
01304                   if (isLike(thisMonth, "jan.*")) imonth = 1;               
01305                   else if (isLike(thisMonth, "feb.*")) imonth = 2;
01306                   else if (isLike(thisMonth, "mar.*")) imonth = 3;
01307                   else if (isLike(thisMonth, "apr.*")) imonth = 4;
01308                   else if (isLike(thisMonth, "may.*")) imonth = 5;
01309                   else if (isLike(thisMonth, "jun.*")) imonth = 6;
01310                   else if (isLike(thisMonth, "jul.*")) imonth = 7;
01311                   else if (isLike(thisMonth, "aug.*")) imonth = 8;
01312                   else if (isLike(thisMonth, "sep.*")) imonth = 9;
01313                   else if (isLike(thisMonth, "oct.*")) imonth = 10;
01314                   else if (isLike(thisMonth, "nov.*")) imonth = 11;
01315                   else if (isLike(thisMonth, "dec.*")) imonth = 12;
01316                   else
01317                   {
01318                      FormatException fe("Invalid month entry for setToString");
01319                      GPSTK_THROW(fe);
01320                   }
01321                   hmonth = true;
01322                }
01323                break;
01324 
01325                case 'Y':
01326                {
01327                   iyear = asInt(toBeRemoved);
01328                   hyear = true;
01329                }
01330                break;
01331 
01332                case 'y':
01333                {
01334                   if (fieldLength == 2)
01335                   {
01336                      iyear = asInt(toBeRemoved) + 1900;
01337                      if (iyear < 1980)
01338                         iyear += 100;
01339                   }
01340                   else if (fieldLength == 3)
01341                   {
01342                      iyear = asInt(toBeRemoved) + 1000;
01343                      if (iyear < 1980)
01344                         iyear += 100;
01345                   }
01346                   else
01347                      iyear = asInt(toBeRemoved);
01348 
01349                   hyear = true;
01350                }
01351                break;
01352 
01353                case 'a':
01354                case 'A':
01355                {
01356                   string thisDay = firstWord(toBeRemoved);
01357                   lowerCase(thisDay);
01358                   if (isLike(thisDay, "sun.*")) idow = 0;
01359                   else if (isLike(thisDay, "mon.*")) idow = 1;
01360                   else if (isLike(thisDay, "tue.*")) idow = 2;
01361                   else if (isLike(thisDay, "wed.*")) idow = 3;
01362                   else if (isLike(thisDay, "thu.*")) idow = 4;
01363                   else if (isLike(thisDay, "fri.*")) idow = 5;
01364                   else if (isLike(thisDay, "sat.*")) idow = 6;
01365                   else
01366                   {
01367                      FormatException fe("Invalid day of week for setTostring");
01368                      GPSTK_THROW(fe);
01369                   }
01370                   hdow = true;
01371                }
01372                break;
01373 
01374                case 'm':
01375                {
01376                   imonth = asInt(toBeRemoved);
01377                   hmonth = true;
01378                }
01379                break;
01380 
01381                case 'd':
01382                {
01383                   iday = asInt(toBeRemoved);
01384                   hday = true;
01385                }
01386                break;
01387 
01388                case 'H':
01389                {
01390                   ihour = asInt(toBeRemoved);
01391                   hhour = true;
01392                }
01393                break;
01394 
01395                case 'M':
01396                {
01397                   imin = asInt(toBeRemoved);
01398                   hmin = true;
01399                }
01400                break;
01401 
01402                case 'S':
01403                {
01404                   isec = asDouble(toBeRemoved);
01405                   isec = double(short(isec));
01406                   hsec = true;
01407                }
01408                break;
01409 
01410                case 'f':
01411                {
01412                   isec = asDouble(toBeRemoved);
01413                   hsec = true;
01414                }
01415                break;
01416 
01417                case 'U':
01418                {
01419                   unixsec = asInt(toBeRemoved);
01420                   hunixsec = true;
01421                }
01422                break;
01423 
01424                case 'u':
01425                {
01426                   unixusec = asInt(toBeRemoved);
01427                   hunixusec = true;
01428                }
01429                break;
01430 
01431                case 'C':
01432                {
01433                   ifullzcount = asInt(toBeRemoved);
01434                   hfullzcount = true;
01435                }
01436 
01437                default:
01438                {
01439                      // do nothing
01440                }
01441                break;
01442             }
01443                // remove the part of s that we processed
01444             stripLeading(s,toBeRemoved,1);
01445             
01446                // remove the character we processed from f
01447             f.erase(0,1);    
01448          }
01449          
01450          if ( s.length() != 0  ) 
01451          {
01452                // throw an error - something didn't get processed in the strings
01453             FormatException fe(
01454                "Processing error - parts of strings left unread - " + s);
01455             GPSTK_THROW(fe);
01456          }
01457          
01458          if (f.length() != 0)
01459          {
01460                // throw an error - something didn't get processed in the strings
01461             FormatException fe(
01462                "Processing error - parts of strings left unread - " + f);
01463             GPSTK_THROW(fe);
01464          }
01465          
01466          if (!hmjd && !hsow && !hweek && !hfullWeek && !hdow && !hmonth &&
01467              !hday&& !hzcount && !hdoy && !hfullzcount && !hhour && !hmin &&
01468              !hsec && !hsod && !hunixsec && !hunixusec)
01469          {
01470             FormatException fe("Incomplete time specification for setToString");
01471             GPSTK_THROW(fe);
01472          }
01473 
01474             // GPS time formats
01475          if (hsow)
01476             toReturn.setGPSfullweek(0, isow);
01477          if (hdow && !hsow)
01478             toReturn.setGPSfullweek(0, idow * double(SEC_DAY));
01479          if (hzcount)
01480             toReturn.setGPSfullweek(0, izcount);
01481          if (hfullzcount)
01482             toReturn.setGPS(ifullzcount);
01483          if (hfullWeek)
01484             toReturn.setGPSfullweek(ifullWeek, toReturn.GPSsow());
01485          if (hweek)  // iyear has been set in any case
01486             toReturn.setGPS(iweek, toReturn.GPSsow(), iyear);
01487 
01488             // Calendar time formats
01489             /*
01490             *  Due to inconsistency in number of days/month and 
01491             *  number of days/year, the call to setYMDHMS() needs
01492             *  to be performed as an atomic call.  Changing the pieces
01493             *  individually can lead to inconsistencies in the 
01494             *  transient states.
01495             */
01496          if (hyear || hmonth || hday || hhour || hmin || hsec )
01497          {
01498             int nyear = toReturn.year();
01499             int nmonth = toReturn.month();
01500             int nday = toReturn.day();
01501             int nhour = toReturn.hour();
01502             int nmin = toReturn.minute();
01503             double dsec = toReturn.second();
01504          
01505             if (hyear) nyear = iyear;
01506             if (hmonth) nmonth = imonth;
01507             if (hday) nday = iday;
01508             if (hhour) nhour = ihour;
01509             if (hmin) nmin = imin;
01510             if (hmin) dsec = isec;
01511             toReturn.setYMDHMS(nyear, nmonth, nday,
01512                             nhour, nmin, dsec);
01513          }
01514          
01515             // DOY time formats
01516          if (hdoy)
01517             toReturn.setYDoySod(toReturn.year(), idoy, toReturn.DOYsecond());
01518          if (hsod)
01519             toReturn.setYDoySod(toReturn.year(), toReturn.DOY(), isod);
01520 
01521             // MJD time format
01522          if (hmjd)
01523             toReturn.setMJD(imjd);
01524 
01525             // unix time formats
01526          if (hunixsec || hunixusec)
01527          {
01528             struct timeval tv = toReturn.unixTime();
01529             if (hunixsec) tv.tv_sec = unixsec;
01530             if (hunixusec) tv.tv_usec = unixusec;
01531 
01532             toReturn.setUnix(tv);
01533          }
01534          
01535          *this = toReturn;
01536          return *this;
01537       }
01538       catch(gpstk::Exception& exc)
01539       {
01540          DayTime::DayTimeException dte(exc);
01541          dte.addText("Cannot generate time");
01542          GPSTK_THROW(dte);
01543       }
01544       catch(std::exception& exc)
01545       {
01546          DayTime::DayTimeException dte(exc.what());
01547          dte.addText("Cannot generate time");
01548          GPSTK_THROW(dte);
01549       }
01550    }
01551 
01552       // Format this time into a string.
01553    string DayTime::printf(const char *fmt) const
01554       throw(gpstk::StringUtils::StringException)
01555    {
01556       string rv = fmt;
01557       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*S"), 
01558                           string("Sd"), (short)second());
01559       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*(\\.[[:digit:]]+)?f"),
01560                           string("ff"), second());
01561       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*G"),
01562                           string("Ghd"), GPS10bitweek());
01563       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*F"),
01564                           string("Fhd"), GPSfullweek());
01565       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*(\\.[[:digit:]]+)?g"),
01566                           string("gf"), GPSsow());
01567       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*(\\.[[:digit:]]+)?s"),
01568                           string("sf"), DOYsecond());
01569       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*(\\.[[:digit:]]+)?Q"),
01570                           string("QLf"), getMJDasLongDouble());
01571       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*Y"),
01572                           string("Yhd"), year());
01573       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*y"),
01574                           string("yhd"), (short)(year() % 100));
01575       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*m"),
01576                           string("mhd"), month());
01577       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*b"),
01578                           string("bs"), MonthAbbrevNames[month()]);
01579       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*B"),
01580                           string("Bs"), MonthNames[month()]);
01581       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*d"),
01582                           string("dhd"), day());
01583       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*H"),
01584                           string("Hhd"), hour());
01585       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*M"),
01586                           string("Mhd"), minute());
01587       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*w"),
01588                           string("whd"), dayOfWeek());
01589       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*a"),
01590                           string("as"), DayOfWeekAbbrevNames[dayOfWeek()]);
01591       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*A"),
01592                           string("As"), DayOfWeekNames[dayOfWeek()]);
01593       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*z"),
01594                           string("zd"), GPSzcountFloor());
01595       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*Z"),
01596                           string("Zd"), GPSzcount());
01597       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*U"),
01598                           string("Ud"), unixTime().tv_sec);
01599       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*u"),
01600                           string("ud"), unixTime().tv_usec);
01601       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*j"),
01602                           string("jhd"), DOY());
01603       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*C"),
01604                           string("Cd"), fullZcount());
01605       rv = formattedPrint(rv, string("%[ 0-]?[[:digit:]]*c"),
01606                           string("cd"), fullZcountFloor());
01607 
01608       return rv;
01609    }
01610 
01611    std::string DayTime::toString(int decimals,char datesep, char timesep) const
01612       throw(gpstk::StringUtils::StringException)
01613    {
01614       string fmt = FormatUtils::format("%%04Y%c%%02m%c%%02d %%02H%c%%02M%c%%0%2.0f",
01615                                         datesep,datesep,timesep,timesep);
01616       if(decimals>0)
01617       {
01618          fmt = FormatUtils::format("%%04Y%c%%02m%c%%02d %%02H%c%%02M%c%%0%d.%df",
01619                                    datesep,datesep,timesep,timesep,
01620                                    3+decimals,decimals);
01621       }
01622 
01623       return printf(fmt);
01624    }
01625 
01626       // Format this time into a string.
01627    std::string DayTime::asString() const
01628       throw(gpstk::StringUtils::StringException)
01629    {
01630       ostringstream o;
01631       o << *this;
01632       return o.str();
01633    }
01634 
01635      // Dump everything possible, using every get() TD: keep?
01636    void DayTime::dump(std::ostream& s) const
01637       throw(DayTime::DayTimeException)
01638    {
01639       // warning: the internal representation, even for objects that are equal
01640       // within the tolerance, may be very different
01641 
01642       s << "  internal: jday " << jday << endl;
01643       s << "  internal: mSod " << mSod << endl;
01644       s << "  internal: mSec " << fixed << setprecision(15) << mSec << endl;
01645       s << "  internal: tolerance " << fixed << setprecision(15) << tolerance << endl;
01646       s << "  double JD(): " << fixed << setprecision(6) << JD() << endl;
01647       s << "  double MJD(): " << fixed << setprecision(6) << MJD() << endl;
01648       s << "  short year(): " << year() << endl;
01649       s << "  short month(): " << month() << endl;
01650       s << "  short day(): " << day() << endl;
01651       s << "  short dayOfWeek(): " << dayOfWeek() << endl;
01652       int yy,mm,dd;
01653       getYMD(yy, mm, dd);
01654       s << "  void getYMD(int& yy, int& mm, int& dd): " << yy << " " << mm
01655         << " " << dd << endl;
01656       s << "  short hour(): " << hour() << endl;
01657       s << "  short minute(): " << minute() << endl;
01658       s << "  double second(): " << fixed << setprecision(6) << second() 
01659         << endl;
01660       s << "  double secOfDay(): " << fixed << setprecision(6) << secOfDay() 
01661         << endl;
01662       s << "  short GPS10bitweek(): " << GPS10bitweek() << endl;
01663       s << "  long GPSzcount(): " << GPSzcount() << endl;
01664       s << "  long GPSzcountFloor(): " << GPSzcountFloor() << endl;
01665       s << "  double GPSsecond(): " << fixed << setprecision(6) << GPSsecond() 
01666         << endl;
01667       s << "  double GPSsow(): " << fixed << setprecision(6) << GPSsow() 
01668         << endl;
01669       s << "  short GPSday(): " << GPSday() << endl;
01670       s << "  short GPSfullweek(): " << GPSfullweek() << endl;
01671       s << "  short GPSyear(): " << GPSyear() << endl;
01672       s << "  short DOYyear(): " << DOYyear() << endl;
01673       s << "  short DOYday(): " << DOYday() << endl;
01674       s << "  short DOY(): " << DOY() << endl;
01675       s << "  double DOYsecond(): "<< fixed << setprecision(6) << DOYsecond() 
01676         << endl;
01677       s << "  double MJDdate(): " << fixed << setprecision(6) << MJDdate() 
01678         << endl;
01679       s << "  long double getMJDasLongDouble(): "
01680          << fixed << setprecision(6) << getMJDasLongDouble() << endl;
01681       struct timeval tv=unixTime();
01682       s << "  struct timeval unixTime(): " << tv.tv_sec << " " << tv.tv_usec 
01683         << endl;
01684       s << "  unsigned long fullZcount(): " << fullZcount() << endl;
01685       s << "  unsigned long fullZcountFloor(): " << fullZcountFloor() << endl;
01686    }
01687 
01688       // ----------- Part 11: functions: fundamental conversions -----------
01689       //
01690       // These two routines convert 'integer JD' and calendar time; they were
01691       // derived from Sinnott, R. W. "Bits and Bytes" Sky & Telescope Magazine,
01692       // Vol 82, p. 183, August 1991, and The Astronomical Almanac, published
01693       // by the U.S. Naval Observatory.
01694       // NB range of applicability of this routine is from 0JD (4713BC)
01695       // to approx 3442448JD (4713AD).
01696    void DayTime::convertJDtoCalendar(long jd, 
01697                                      int& iyear, 
01698                                      int& imonth,
01699                                      int& iday)
01700       throw()
01701    {
01702       long L, M, N, P, Q;
01703       if(jd > 2299160)    // after Oct 4, 1582
01704       {
01705          L = jd + 68569;
01706          M = (4 * L) / 146097;
01707          L = L - ((146097 * M + 3) / 4);
01708          N = (4000 * (L + 1)) / 1461001;
01709          L = L - ((1461 * N) / 4) + 31;
01710          P = (80 * L) / 2447;
01711          iday = int(L - (2447 * P) / 80);
01712          L = P / 11;
01713          imonth = int(P + 2 - 12 * L);
01714          iyear = int(100 * (M - 49) + N + L);
01715       }
01716       else 
01717       {
01718          P = jd + 1402;
01719          Q = (P - 1) / 1461;
01720          L = P - 1461 * Q;
01721          M = (L - 1) / 365 - L / 1461;
01722          N = L - 365 * M + 30;
01723          P = (80 * N) / 2447;
01724          iday = int(N - (2447 * P) / 80);
01725          N = P / 11;
01726          imonth = int(P + 2 - 12 * N);
01727          iyear = int(4 * Q + M + N - 4716);
01728          if(iyear <= 0) 
01729          {
01730             --iyear;
01731          }
01732       }
01733          // catch century/non-400 non-leap years
01734       if(iyear > 1599 && 
01735          !(iyear % 100) && 
01736          (iyear % 400) && 
01737          imonth == 2 && 
01738          iday == 29)
01739       {
01740          imonth = 3;
01741          iday = 1;
01742       }
01743    }
01744    
01745    long DayTime::convertCalendarToJD(int yy, 
01746                                      int mm,
01747                                      int dd) 
01748       throw()
01749    {
01750       if(yy == 0)
01751          --yy;         // there is no year 0
01752 
01753       if(yy < 0) 
01754          ++yy;
01755       
01756       long jd;
01757       double y = double(yy), m = double(mm), d = double(dd);
01758 
01759          // In the conversion from the Julian Calendar to the Gregorian
01760          // Calendar the day after October 4, 1582 was October 15, 1582.
01761          //
01762          // if the date is before October 15, 1582
01763       if(yy < 1582 || (yy == 1582 && (mm < 10 || (mm == 10 && dd < 15))))
01764       {
01765          jd = 1729777 + dd + 367 * yy 
01766             - long(7 * ( y + 5001 + long((m - 9) / 7)) / 4) 
01767             + long(275 * m / 9);
01768       }
01769       else   // after Oct 4, 1582
01770       {     
01771         jd = 1721029 + dd + 367 * yy 
01772            - long(7 * (y + long((m + 9) / 12)) / 4)
01773            - long(3 * (long((y + (m - 9) / 7) / 100) + 1) / 4) 
01774            + long(275 * m / 9);
01775 
01776             // catch century/non-400 non-leap years
01777          if( (! (yy % 100) && 
01778               (yy % 400) && 
01779               mm > 2 && 
01780               mm < 9)      || 
01781              (!((yy - 1) % 100) &&
01782               ((yy - 1) % 400) &&
01783               mm == 1)) 
01784          {
01785             --jd;
01786          }
01787       }
01788       return jd;
01789    }
01790 
01791    void DayTime::convertSODtoTime(double sod, 
01792                                   int& hh,
01793                                   int& mm,
01794                                   double& sec) 
01795       throw()
01796    {
01797          // Get us to within one day.
01798       if (sod < 0)
01799       {
01800          sod += (1 + (unsigned long)(sod / SEC_DAY)) * SEC_DAY ;
01801       }
01802       else if (sod >= SEC_DAY)
01803       {
01804          sod -= (unsigned long)(sod / SEC_DAY) * SEC_DAY ;
01805       }
01806       
01807       double temp;               // variable to hold the integer part of sod
01808       sod = modf(sod, &temp);    // sod holds the fraction, temp the integer
01809       long seconds = long(temp); // get temp into a real integer
01810 
01811       hh = seconds / 3600 ;
01812       mm = (seconds % 3600) / 60 ;
01813       sec = double(seconds % 60) + sod ;
01814 
01815    }
01816 
01817    double DayTime::convertTimeToSOD(int hh, 
01818                                     int mm,
01819                                     double sec) 
01820       throw()
01821    {
01822       return (sec + 60. * (mm + 60. * hh));
01823    }
01824 
01825       // ----------- Part 12: private functions and member data -----------
01826       //
01827    void DayTime::init()
01828       throw()
01829    {
01830       timeFrame = Unknown;
01831       tolerance = DAYTIME_TOLERANCE;
01832       jday = 0;
01833       mSod = 0;
01834       mSec = 0.0;
01835    }
01836 
01837    // ldd is days, lds is milliseconds, and ds is milliseconds
01838    void DayTime::addLongDeltaTime(long ldd, 
01839                                   long lds,
01840                                   double ds)
01841       throw(DayTime::DayTimeException)
01842    {
01843          // We preprocess the input to avoid overflow when
01844          // convert from double to long. Wei Yan(2010-07-27)
01845         
01846       ldd += long(ds / MS_PER_DAY);
01847       ds -= long(ds / MS_PER_DAY) * double(MS_PER_DAY);   
01848  
01849 
01850          // Use temp variables so that we don't modify our
01851          // data members until we know these values are good.
01852       long workingJday(jday), workingMsod(mSod) ;
01853       double workingMsec(mSec), temp(0) ;
01854       
01855       workingMsec += ds ;
01856          // check that workingMsod is not out of bounds
01857       if (workingMsec < 0.)
01858       {
01859             // split workingMsec into integer and fraction parts
01860             // workingMsec gets the fraction and temp gets the integer
01861          workingMsec = 1 + modf(workingMsec, &temp);
01862             // add the (negative) integer milliseconds to lds
01863          if(workingMsec == 1) {
01864             workingMsec = 0;
01865             lds += long(temp);
01866          }
01867          else
01868             lds += long(temp) -  1;
01869       }
01870       else if (workingMsec >= 1.0)
01871       {
01872             // same as above
01873          workingMsec = modf(workingMsec, &temp) ;
01874             // add the integer milliseconds to lds
01875          lds += long(temp) ;         
01876       }
01877       
01878       workingMsod += lds ;
01879          // add any full days to ldd
01880       ldd += workingMsod / (SEC_DAY * FACTOR) ;
01881 
01882          // this will get us here:
01883          // -(SEC_DAY * FACTOR) < workingMsod < (SEC_DAY * FACTOR)
01884       workingMsod %= (SEC_DAY * FACTOR) ;
01885 
01886          // this will get us here: 0 <= workingMsod < (SEC_DAY * FACTOR)
01887       if (workingMsod < 0)
01888       {
01889          workingMsod += (SEC_DAY * FACTOR) ;
01890          --ldd ;
01891       }
01892 
01893       workingJday += ldd ;
01894          // check that workingJday is not out of bounds
01895       if(workingJday < BEGIN_LIMIT_JDAY)
01896       {
01897          DayTime::DayTimeException dte("DayTime underflow") ;
01898          GPSTK_THROW(dte) ;
01899       }
01900       if(workingJday > END_LIMIT_JDAY)
01901       {
01902          DayTime::DayTimeException dte("DayTime overflow") ;
01903          GPSTK_THROW(dte) ;
01904       }
01905       
01906          // everything's OK, so set the data members
01907       jday = workingJday ;
01908       mSod = workingMsod ;
01909       mSec = workingMsec ;
01910 
01911       realignInternals();
01912    }
01913 
01914       // Helper routine to realign the internal representation in order to
01915       // avoid incorrect output (printf) when mSec is within tolerance of 1
01916    void DayTime::realignInternals(void)
01917       throw()
01918    {
01919       if(fabs(mSec-1)/FACTOR < tolerance) {
01920          // decrement mSec, except mSec must not be negative
01921          // alternately, set mSec = 0, but perhaps this contributes numerical noise?
01922          mSec = (mSec-1 < 0 ? 0 : mSec-1);
01923          mSod += 1;
01924       }
01925       if(mSod >= SEC_DAY*FACTOR) {
01926          mSod -= SEC_DAY*FACTOR;
01927          jday += 1;
01928       }
01929    }
01930 
01931       // ----------- Part 13: operator<< --------------
01932       //
01933       // Stream output for DayTime objects.  Typically used for debugging.
01934       // @param s stream to append formatted DayTime to.
01935       // @param t DayTime to append to stream \c s.
01936       // @return reference to \c s.
01937    ostream& operator<<( ostream& s, 
01938                         const DayTime& t )
01939    {
01940       s << t.printf("%02m/%02d/%04Y %02H:%02M:%02S");
01941       return s;
01942    }
01943 
01944 }   // end namespace gpstk
01945 

Generated on Mon Jun 18 03:30:56 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1