Epoch.cpp

Go to the documentation of this file.
00001 #pragma ident "$Id: Epoch.cpp 1163 2008-03-28 13:01:33Z snelsen $"
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 
00047 #include <iostream>
00048 #include <iomanip>
00049 #include <string>
00050 #include <ctime>
00051 
00052 #include "gpstkplatform.h"
00053 #include "Epoch.hpp"
00054 
00055 #include "TimeConstants.hpp"
00056 #include "TimeString.hpp"
00057 
00058 #include "JulianDate.hpp"
00059 #include "MJD.hpp"
00060 #include "YDSTime.hpp"
00061 #include "CivilTime.hpp"
00062 #include "GPSWeekZcount.hpp"
00063 #include "GPSWeekSecond.hpp"
00064 
00065 
00066 namespace gpstk
00067 {
00068    using namespace std;
00069    using namespace gpstk::StringUtils;
00070 
00071       // One nanosecond tolerance.
00072    const double Epoch::ONE_NSEC_TOLERANCE = 1e-9;
00073       // One microsecond tolerance.
00074    const double Epoch::ONE_USEC_TOLERANCE = 1e-6;
00075       // One millisecond tolerance.
00076    const double Epoch::ONE_MSEC_TOLERANCE = 1e-3;
00077       // One second tolerance.
00078    const double Epoch::ONE_SEC_TOLERANCE = 1;
00079       // One minute tolerance.
00080    const double Epoch::ONE_MIN_TOLERANCE = 60;
00081       // One hour tolerance.
00082    const double Epoch::ONE_HOUR_TOLERANCE = 3600;
00083    
00084       // Tolerance for time equality.
00085 #ifdef _WIN32
00086    double Epoch::EPOCH_TOLERANCE = ONE_USEC_TOLERANCE;
00087 #else
00088    double Epoch::EPOCH_TOLERANCE = ONE_NSEC_TOLERANCE;
00089 #endif
00090 
00092    const Epoch BEGINNING_OF_TIME(CommonTime::BEGINNING_OF_TIME);
00094    const Epoch END_OF_TIME(CommonTime::END_OF_TIME);
00095 
00096    std::string Epoch::PRINT_FORMAT("%02m/%02d/%04Y %02H:%02M:%02S");
00097 
00098    Epoch& Epoch::setTolerance(double tol)
00099       throw()
00100    {
00101       tolerance = tol;
00102       return *this;
00103    }
00104    
00105       // Default constructor; initializes to current system time.
00106    Epoch::Epoch(const TimeTag& tt)
00107       throw(Epoch::EpochException)
00108          : tolerance(EPOCH_TOLERANCE)
00109    {
00110       set(tt);
00111    }
00112 
00113    Epoch::Epoch(const CommonTime& ct)
00114       throw()
00115          : tolerance(EPOCH_TOLERANCE),
00116            core(ct)
00117    {}
00118 
00123    Epoch::Epoch(const TimeTag& tt,
00124                 short year)
00125       throw(Epoch::EpochException)
00126          : tolerance(EPOCH_TOLERANCE)
00127    {
00128       set(tt, year);
00129    }
00130 
00131       // GPS Zcount constructor.
00132       // @param z GPSZcount object to set to
00133       // @param f Time frame (see #TimeFrame)
00134    Epoch::Epoch(const GPSZcount& z)
00135       throw()
00136          : tolerance(EPOCH_TOLERANCE)
00137    {
00138       set(z);
00139    }
00140 
00141       // Copy constructor
00142    Epoch::Epoch(const Epoch& right)
00143       throw()
00144          : core(right.core),
00145            tolerance(right.tolerance)
00146    {}
00147 
00148       // Assignment operator.
00149    Epoch& Epoch::operator=(const Epoch& right)
00150       throw()
00151    {
00152       core = right.core;
00153       tolerance = right.tolerance;
00154       return *this;
00155    }
00156 
00157       // Epoch difference function.
00158       // @param right Epoch to subtract from this one.
00159       // @return difference in seconds.
00160    double Epoch::operator-(const Epoch& right) const
00161       throw()
00162    {
00163       return core - right.core;
00164    }
00165 
00166       // Add seconds to this time.
00167       // @param seconds Number of seconds to increase this time by.
00168       // @return The new time incremented by \c seconds.
00169    Epoch Epoch::operator+(double seconds) const
00170       throw(Epoch::EpochException)
00171    {
00172       return Epoch(*this).addSeconds(seconds);
00173    }
00174 
00175       // Subtract seconds from this time.
00176       // @param seconds Number of seconds to decrease this time by.
00177       // @return The new time decremented by \c seconds.
00178    Epoch Epoch::operator-(double seconds) const
00179       throw(Epoch::EpochException)
00180    {
00181       return Epoch(*this).addSeconds(-seconds);
00182    }
00183 
00184       // Add seconds to this time.
00185       // @param seconds Number of seconds to increase this time by.
00186    Epoch& Epoch::operator+=(double seconds)
00187       throw(Epoch::EpochException)
00188    {
00189       return addSeconds(seconds);
00190    }
00191    
00192       // Subtract seconds from this time.
00193       // @param sec Number of seconds to decrease this time by.
00194    Epoch& Epoch::operator-=(double seconds)
00195       throw(Epoch::EpochException)
00196    {
00197       return addSeconds(-seconds);
00198    }
00199 
00200       // Add seconds to this object.
00201       // @param seconds Number of seconds to add
00202    Epoch& Epoch::addSeconds(double seconds)
00203       throw(Epoch::EpochException)
00204    {
00205       try
00206       {
00207          core.addSeconds(seconds);
00208          return *this;
00209       }
00210       catch( InvalidRequest& ir )
00211       {
00212          Epoch::EpochException ee(ir);
00213          GPSTK_THROW(ee);
00214       }
00215    }
00216 
00217       // Add (integer) seconds to this object.
00218       // @param seconds Number of seconds to add.
00219    Epoch& Epoch::addSeconds(long seconds)
00220       throw(Epoch::EpochException)
00221    {
00222       try
00223       {
00224          core.addSeconds(seconds);
00225          return *this ;
00226       }
00227       catch( InvalidRequest& ir )
00228       {
00229          Epoch::EpochException ee(ir);
00230          GPSTK_THROW(ee);
00231       }
00232    }
00233 
00234       // Add (integer) milliseconds to this object.
00235       // @param msec Number of milliseconds to add.
00236    Epoch& Epoch::addMilliSeconds(long msec)
00237       throw(Epoch::EpochException)
00238    {
00239       try
00240       {
00241          core.addMilliseconds(msec);
00242          return *this;
00243       }
00244       catch( InvalidRequest& ir )
00245       {
00246          Epoch::EpochException ee(ir);
00247          GPSTK_THROW(ee);
00248       }
00249    }
00250 
00251       // Add (integer) microseconds to this object.
00252       // @param usec Number of microseconds to add.
00253    Epoch& Epoch::addMicroSeconds(long usec)
00254       throw(Epoch::EpochException)
00255    {
00256       try
00257       {
00258          long ms = usec / 1000;     // whole milliseconds
00259          usec -= ms * 1000;         // leftover microseconds
00260          core.addMilliseconds(ms);
00261             // us * 1ms/1000us * 1s/1000ms
00262          core.addSeconds(static_cast<double>(usec) * 1e-6);
00263          return *this;
00264       }
00265       catch( InvalidRequest& ir )
00266       {
00267          Epoch::EpochException ee(ir);
00268          GPSTK_THROW(ee);
00269       }
00270    }
00271 
00272       // Equality operator.
00273    bool Epoch::operator==(const Epoch &right) const 
00274       throw()
00275    {
00276       // use the smaller of the two tolerances for comparison
00277       return (ABS(operator-(right)) <=
00278          ((tolerance > right.tolerance) ? right.tolerance : tolerance));
00279    }
00280 
00281       // Inequality operator.
00282    bool Epoch::operator!=(const Epoch &right) const 
00283       throw()
00284    {
00285       return !(operator==(right));
00286    }
00287 
00288       // Comparison operator (less-than).
00289    bool Epoch::operator<(const Epoch &right) const 
00290       throw()
00291    {
00292       return (operator-(right) <
00293             -((tolerance > right.tolerance) ? right.tolerance : tolerance));
00294    }
00295 
00296       // Comparison operator (greater-than).
00297    bool Epoch::operator>(const Epoch &right) const 
00298       throw()
00299    {
00300       return (operator-(right) >
00301             ((tolerance > right.tolerance) ? right.tolerance : tolerance));
00302    }
00303    
00304       // Comparison operator (less-than or equal-to).
00305    bool Epoch::operator<=(const Epoch &right) const 
00306       throw()
00307    {
00308       return !(operator>(right));
00309    }
00310 
00311       // Comparison operator (greater-than or equal-to).
00312    bool Epoch::operator>=(const Epoch &right) const 
00313       throw()
00314    {
00315       return !(operator<(right));
00316    }
00317 
00318    template <class TimeTagType>
00319    TimeTagType Epoch::get() const
00320       throw(Epoch::EpochException)
00321    {
00322       try
00323       {
00324          return TimeTagType(core);
00325       }
00326       catch( Exception& e)
00327       {
00328          EpochException ee(e);
00329          GPSTK_THROW(ee);
00330       }
00331    }
00332    
00336    long double Epoch::JD() const
00337       throw(Epoch::EpochException)
00338    {
00339       return get<JulianDate>().jd;
00340    }
00341    
00345    long double Epoch::MJD() const
00346       throw(Epoch::EpochException)
00347    {
00348       return get<gpstk::MJD>().mjd;
00349    }
00350    
00352    short Epoch::year() const
00353       throw(Epoch::EpochException)
00354    {
00355       return static_cast<short>(get<CivilTime>().year);
00356    }
00357    
00359    short Epoch::month() const
00360       throw(Epoch::EpochException)
00361    {
00362       return static_cast<short>(get<CivilTime>().month);
00363    }
00364    
00366    short Epoch::day() const
00367       throw(Epoch::EpochException)
00368    {
00369       return static_cast<short>(get<CivilTime>().day);
00370    }
00371    
00373    short Epoch::dow() const
00374       throw(Epoch::EpochException)
00375    {
00376       return (((static_cast<long>(JD()) % 7) + 1) % 7) ;
00377    }
00378    
00380    short Epoch::hour() const
00381       throw(Epoch::EpochException)
00382    {
00383       return static_cast<short>(get<CivilTime>().hour);
00384    }
00385    
00387    short Epoch::minute() const
00388       throw(Epoch::EpochException)
00389    {
00390       return static_cast<short>(get<CivilTime>().minute);
00391    }
00392    
00394    double Epoch::second() const
00395       throw(Epoch::EpochException)
00396    {
00397       return get<CivilTime>().second;
00398    }
00399    
00401    double Epoch::sod() const
00402       throw(Epoch::EpochException)
00403    {
00404       return get<YDSTime>().sod;
00405    }
00406    
00408    short Epoch::GPSweek10() const
00409       throw(Epoch::EpochException)
00410    {
00411       return static_cast<short>(get<GPSWeekSecond>().getWeek10());
00412    }
00413    
00415    long Epoch::GPSzcount() const
00416       throw(Epoch::EpochException)
00417    {
00418       return get<GPSWeekZcount>().zcount;
00419    }
00420    
00422    long Epoch::GPSzcountFloor() const
00423       throw(Epoch::EpochException)
00424    {
00425       Epoch e = *this + .75; // add half a zcount
00426       return e.get<GPSWeekZcount>().zcount;
00427    }
00428    
00434    unsigned long Epoch::GPSzcount32() const
00435       throw(Epoch::EpochException)
00436    {
00437       return get<GPSWeekZcount>().getZcount32();
00438    }
00439    
00441    unsigned long Epoch::GPSzcount32Floor() const
00442       throw(Epoch::EpochException)
00443    {
00444       Epoch e = *this + .75; // add half a zcount
00445       return e.get<GPSWeekZcount>().getZcount32();
00446    }
00447    
00449    double Epoch::GPSsow() const
00450       throw(Epoch::EpochException)
00451    {
00452       return get<GPSWeekSecond>().sow;
00453    }
00454    
00456    short Epoch::GPSweek() const
00457       throw(Epoch::EpochException)
00458    {
00459       return static_cast<short>(get<GPSWeekSecond>().week);
00460    }
00461    
00463    short Epoch::doy() const
00464       throw(Epoch::EpochException)
00465    {
00466       return static_cast<short>(get<YDSTime>().doy);
00467    }
00468    
00470    struct timeval Epoch::unixTime() const
00471       throw(Epoch::EpochException)
00472    {
00473       return get<UnixTime>().tv;
00474    }
00475    
00476    Epoch::operator GPSZcount() const
00477       throw(Epoch::EpochException)
00478    {
00479       try
00480       {
00481             // this wants a rounded zcount
00482          Epoch e = *this + 0.75;
00483          GPSWeekZcount wz = get<GPSWeekZcount>();
00484          return GPSZcount(wz.week, wz.zcount);
00485       }
00486       catch (gpstk::InvalidParameter& ip)
00487       {
00488          Epoch::EpochException ee(ip);
00489          GPSTK_THROW(ee);
00490       }
00491    }
00492 
00493    Epoch::operator CommonTime() const
00494       throw()
00495    {
00496       return core;
00497    }
00498 
00499    Epoch& Epoch::set(const TimeTag& tt)
00500       throw(Epoch::EpochException)
00501    {
00502       try
00503       {
00504          core = tt;
00505          return *this;
00506       }
00507       catch(InvalidParameter& ip)
00508       {
00509          EpochException ee(ip);
00510          GPSTK_THROW(ee);
00511       }
00512    }
00513 
00514    Epoch& Epoch::set(const TimeTag& tt,
00515                      short year)
00516       throw(Epoch::EpochException)
00517    {
00518       try
00519       { 
00520          GPSWeekSecond ws(tt);
00521          ws.setEpoch(whichGPSEpoch(ws.getWeek10(), year));
00522          core = ws;
00523          return *this;
00524       }
00525       catch(InvalidParameter& ip)
00526       {
00527          EpochException ee(ip);
00528          GPSTK_THROW(ee);
00529       }
00530    }
00531 
00532    Epoch& Epoch::set(const CommonTime& c)
00533       throw()
00534    {
00535       core = c;
00536       return *this;
00537    }
00538 
00539       // Set the object's time using the given GPSZcount.
00540       // System time is used to disambiguate which 1024 week 'zone'
00541       // is appropriate.
00542       // @param z the GPSZcount object to set to
00543       // @param f Time frame (see #TimeFrame)
00544       // @return a reference to this object.
00545    Epoch& Epoch::set(const GPSZcount& z)
00546       throw(Epoch::EpochException)
00547    {
00548       try
00549       {
00550          GPSWeekZcount wz(core);
00551          wz.week = z.getWeek();
00552          wz.zcount = z.getZcount();
00553          core = wz;
00554          return *this ;
00555       }
00556       catch(Exception& exc)
00557       {
00558          EpochException ee(exc);
00559          GPSTK_THROW(ee);
00560       }
00561    }
00562 
00563    Epoch& Epoch::setTime(const CommonTime& ct)
00564       throw(Epoch::EpochException)
00565    {
00566       try
00567       {
00568          long myDAY, mySOD, ctDAY, ctSOD;
00569          double myFSOD, ctFSOD;
00570          core.get(myDAY, mySOD, myFSOD);
00571          ct.get(ctDAY, ctSOD, ctFSOD);
00572          core.set(myDAY, ctSOD, ctFSOD);
00573          return *this;
00574       }
00575       catch(InvalidParameter& ip)
00576       {
00577          EpochException ee(ip);
00578          GPSTK_THROW(ee);
00579       }
00580    }
00581    
00582    Epoch& Epoch::setDate(const CommonTime& ct)
00583       throw(Epoch::EpochException)
00584    {
00585       try
00586       {
00587          long myDAY, mySOD, ctDAY, ctSOD;
00588          double myFSOD, ctFSOD;
00589          core.get(myDAY, mySOD, myFSOD);
00590          ct.get(ctDAY, ctSOD, ctFSOD);
00591          core.set(ctDAY, mySOD, myFSOD);
00592          return *this;
00593       }
00594       catch(InvalidParameter& ip)
00595       {
00596          EpochException ee(ip);
00597          GPSTK_THROW(ee);
00598       }
00599    }
00600    
00601       // set using local time
00602    Epoch& Epoch::setLocalTime()
00603       throw(Epoch::EpochException)
00604    {
00605       time_t t;
00606       time(&t);
00607       struct tm  *ltod;
00608       ltod = localtime(&t);
00609       return set(CivilTime(1900 + ltod->tm_year, 
00610                            ltod->tm_mon + 1,
00611                            ltod->tm_mday,
00612                            ltod->tm_hour,
00613                            ltod->tm_min,
00614                            ltod->tm_sec));
00615    }
00616 
00617    Epoch& Epoch::scanf(const string& str,
00618                        const string& fmt)
00619       throw(StringException)
00620    {
00621       try
00622       {
00623          scanTime( core, str, fmt );
00624          return *this;
00625       }
00626       catch (StringException& se)
00627       {
00628          GPSTK_RETHROW(se);
00629       }
00630    }
00631 
00632       // Format this time into a string.
00633    string Epoch::printf(const string& fmt) const
00634       throw(StringException)
00635    {
00636       try
00637       {
00638          return printTime( core, fmt );
00639       }
00640       catch (StringException& se)
00641       {
00642          GPSTK_RETHROW(se);
00643       }
00644    }
00645 
00646    short Epoch::whichGPSEpoch(int week,
00647                               int year) const
00648       throw(Epoch::EpochException)
00649    {
00650       try
00651       {
00652             // Get the epoch at the start of the given year.
00653          short epoch1 = GPSWeekSecond(CivilTime(year, 1, 1)).getEpoch();
00654             // Get the epoch at the end of the given year.
00655          short epoch2 = GPSWeekSecond(CivilTime(year, 12, 31)).getEpoch();
00656          
00657          if (epoch1 == epoch2)
00658          {
00659                // The GPS 10-bit week *doesn't* rollover during the given year.
00660             return epoch1;
00661          }
00662 
00663          if (week <= 512)
00664          {
00665                // roll-over happened before week -> use epoch2
00666             return epoch2;
00667          }
00668          
00669             // week > 512
00670             // roll-over happened after week -> use epoch1
00671          return epoch1;
00672       }
00673       catch( InvalidParameter& ip )
00674       {
00675          EpochException ee(ip);
00676          GPSTK_THROW(ee);
00677       }
00678    }
00679 
00680       // Stream output for Epoch objects.  Typically used for debugging.
00681       // @param s stream to append formatted Epoch to.
00682       // @param t Epoch to append to stream \c s.
00683       // @return reference to \c s.
00684    ostream& operator<<( ostream& s, 
00685                         const Epoch& e )
00686    {
00687       s << e.printf();
00688       return s;
00689    }
00690 
00691 }   // end namespace gpstk

Generated on Wed Feb 8 03:30:59 2012 for GPS ToolKit Software Library by  doxygen 1.3.9.1