text: /// @file YDSTime.cpp
  
  //============================================================================
  //
  //  This file is part of GPSTk, the GPS Toolkit.
  //
  //  The GPSTk is free software; you can redistribute it and/or modify
  //  it under the terms of the GNU Lesser General Public License as published
  //  by the Free Software Foundation; either version 2.1 of the License, or
  //  any later version.
  //
  //  The GPSTk is distributed in the hope that it will be useful,
  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  //  GNU Lesser General Public License for more details.
  //
  //  You should have received a copy of the GNU Lesser General Public
  //  License along with GPSTk; if not, write to the Free Software Foundation,
  //  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  //
  //  Copyright 2004, The University of Texas at Austin
  //
  //============================================================================
  
  //============================================================================
  //
  //This software developed by Applied Research Laboratories at the University of
  //Texas at Austin, under contract to an agency or agencies within the U.S.
  //Department of Defense. The U.S. Government retains all rights to use,
  //duplicate, distribute, disclose, or release this software.
  //
  //Pursuant to DoD Directive 523024
  //
  // DISTRIBUTION STATEMENT A: This software has been approved for public
  //                           release, distribution is unlimited.
  //
  //=============================================================================
  
  #include <cmath>
  #include "YDSTime.hpp"
  #include "TimeConverters.hpp"
  
  namespace gpstk
  {
  // YDSTime constant corresponding to CommonTime::BEGINNING_OF_TIME
  
  
     const YDSTime YDSTime::BEGIN_TIME(CommonTime::BEGINNING_OF_TIME);
  
     YDSTime& YDSTime::operator=( const YDSTime& right )
     {
        year = right.year;
        doy  = right.doy;
        sod  = right.sod;
        timeSystem = right.timeSystem;
        return *this;
     }
  
     CommonTime YDSTime::convertToCommonTime() const
     {
        try
        {
           long jday = convertCalendarToJD( year, 1, 1 ) + doy - 1;
           CommonTime ct;
           return ct.set( jday, sod, timeSystem );
        }
        catch ( InvalidParameter& ip )
        {
           InvalidRequest ir(ip);
           GPSTK_THROW(ir);
        }
     }
  
     void YDSTime::convertFromCommonTime( const CommonTime& ct )
     {
        long jday, secDay;
        double fsecDay;
        ct.get( jday, secDay, fsecDay, timeSystem );
        sod = static_cast<double>( secDay ) + fsecDay;
  
        int month, day;
        convertJDtoCalendar( jday, year, month, day );
        doy = jday - convertCalendarToJD( year, 1, 1 ) + 1;
     }
  
     std::string YDSTime::printf( const std::string& fmt ) const
     {
        try
        {
           using gpstk::StringUtils::formattedPrint;
           std::string rv = fmt;
  
           rv = formattedPrint( rv, getFormatPrefixInt() + "Y",
                                "Yd", year );
           rv = formattedPrint( rv, getFormatPrefixInt() + "y",
                                "yd", static_cast<short>(year % 100) );
           rv = formattedPrint( rv, getFormatPrefixInt() + "j",
                                "ju", doy );
           rv = formattedPrint( rv, getFormatPrefixFloat() + "s",
                                "sf", sod );
           rv = formattedPrint( rv, getFormatPrefixInt() + "P",
                                "Ps", timeSystem.asString().c_str() );
           return rv;
        }
        catch( gpstk::StringUtils::StringException& exc)
        {
           GPSTK_RETHROW( exc );
        }
     }
  
     std::string YDSTime::printError( const std::string& fmt ) const
     {
        try
        {
           using gpstk::StringUtils::formattedPrint;
           std::string rv = fmt;
  
           rv = formattedPrint( rv, getFormatPrefixInt() + "Y",
                                "Ys", getError().c_str() );
           rv = formattedPrint( rv, getFormatPrefixInt() + "y",
                                "ys", getError().c_str() );
           rv = formattedPrint( rv, getFormatPrefixInt() + "j",
                                "js", getError().c_str() );
           rv = formattedPrint( rv, getFormatPrefixFloat() + "s",
                                "ss", getError().c_str() );
           rv = formattedPrint( rv, getFormatPrefixInt() + "P",
                                "Ps", getError().c_str() );
           return rv;
        }
        catch( gpstk::StringUtils::StringException& exc)
        {
           GPSTK_RETHROW( exc );
        }
     }
  
     bool YDSTime::setFromInfo( const IdToValue& info )
     {
        using namespace gpstk::StringUtils;
  
        for( IdToValue::const_iterator i = info.begin();
             i != info.end(); i++ )
        {
           switch( i->first )
           {
              case 'Y':
                 year = asInt( i->second );
                 break;
  
              case 'y':
                 switch( i->second.length() )
                 {
                    case 2:
                       year = asInt( i->second ) + 1900;
                       if( year < 1980 )
                          year += 100;
                       break;
                    case 3:
                       year = asInt( i->second ) + 1000;
                       if( year < 1980 )
                          year += 100;
                       break;
                    default:
                       year = asInt( i->second );
                       break;
                 };
                 break;
  
              case 'j':
                 doy = asInt( i->second );
                 break;
  
              case 's':
                 sod = asDouble( i->second );
                 break;
  
              case 'P':
                 timeSystem.fromString(i->second);
                 break;
  
              default:
                    // do nothing
                 break;
           };
        }
  
        return true;
     }
  
     bool YDSTime::isValid() const
     {
        YDSTime temp;
        temp.convertFromCommonTime( convertToCommonTime() );
        if( *this == temp )
        {
           return true;
        }
        return false;
     }
  
     void YDSTime::reset()
     {
        year = doy = 0;
        sod = 0.0;
        timeSystem = TimeSystem::Unknown;
     }
  
     bool YDSTime::operator==( const YDSTime& right ) const
     {
       /// Any (wildcard) type exception allowed, otherwise must be same time systems
        if ((timeSystem != TimeSystem::Any &&
             right.timeSystem != TimeSystem::Any) &&
            timeSystem != right.timeSystem)
           return false;
  
        if( year == right.year &&
            doy  == right.doy  &&
            fabs(sod - right.sod) < CommonTime::eps )
        {
           return true;
        }
        return false;
     }
  
     bool YDSTime::operator!=( const YDSTime& right ) const
     {
        return ( !operator==( right ) );
     }
  
     bool YDSTime::operator<( const YDSTime& right ) const
     {
       /// Any (wildcard) type exception allowed, otherwise must be same time systems
        if ((timeSystem != TimeSystem::Any &&
             right.timeSystem != TimeSystem::Any) &&
            timeSystem != right.timeSystem)
        {
           gpstk::InvalidRequest ir("CommonTime objects not in same time system, cannot be compared");
  	 GPSTK_THROW(ir);
        }
  
        if( year < right.year )
        {
           return true;
        }
        if( year > right.year )
        {
           return false;
        }
        if( doy < right.doy )
        {
           return true;
        }
        if( doy > right.doy )
        {
           return false;
        }
        if( sod < right.sod )
        {
           return true;
        }
        return false;
     }
  
     bool YDSTime::operator>( const YDSTime& right ) const
     {
        return ( !operator<=( right ) );
     }
  
     bool YDSTime::operator<=( const YDSTime& right ) const
     {
        return ( operator<( right ) || operator==( right ) );
     }
  
     bool YDSTime::operator>=( const YDSTime& right ) const
     {
        return ( !operator<( right ) );
     }
  
        // ----------- YDSTime operator<< --------------
        //
        // Stream output for YDSTime objects.  Typically used for debugging.
        // @param s stream to append formatted YDSTime to.
        // @param t YDSTime to append to stream \c s.
        // @return reference to \c s.
  
     std::ostream& operator<<( std::ostream& s,
                               const YDSTime& yt )
     {
        s << yt.printf("%04Y/%03j %s %P");
        return s;
     }
  
  
  } // namespace
  