c++boosttimeboost-units

Converting between boost units and durations


I am working on a project involving many measurements and I would like to use boost units to ensure that units are converted correctly. I started by introducing some typedefs to simplify notation:

#include <boost/units/cmath.hpp>
#include <boost/units/io.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/io.hpp>

#include <boost/date_time/posix_time/posix_time.hpp>

namespace Time = boost::posix_time;

typedef Time::ptime DateTime;
typedef Time::time_duration Duration;

namespace Units
{
  using namespace boost::units;

  namespace SI
  {
    using namespace boost::units::si;
  }

  template <class U> using Quantity = quantity<U>;

  typedef Quantity<SI::length> Length;
  typedef Quantity<SI::velocity> Velocity;
  typedef Quantity<SI::time> Time;
}

I have written some code to compute distances and travel times using these units:

// a computation of distances which yields a length
Units::Length distance = origin.distance(destination);

Units::Velocity flight_speed(100 * Units::SI::meter / Units::SI::second);

Units::Time flight_time = distance / flight_speed;

DateTime departure_time = ...

DateTime arrival_time = departure_time + flight_time; // does not work..

This leads to my question: Is there some built-in way to convert between a Duration (aka boost::posix_time::time_duration) and time_duration Units::Quantity<SI::time> (aka boost::units::quantity<boost::units::si::time>)? It seems like this should be built-in, but I did not find anything in the documentation about it.


Solution

  • You have to do the work:

    DateTime arrival_time = departure_time +
         boost::posix_time::seconds(flight_time / Units::SI::second);
    

    Of course, you could hide the conversion in a helper of sorts:

    static inline DateTime operator+(DateTime const &lhs, Units::Time const &rhs) {
        return lhs + Time::seconds(rhs / Units::SI::second);
    }
    static inline DateTime operator-(DateTime const &lhs, Units::Time const &rhs) {
        return lhs - Time::seconds(rhs / Units::SI::second);
    }
    

    Now you can write

    auto arrival_time = departure_time + flight_time;
    

    Live On Coliru

    #include <boost/units/cmath.hpp>
    #include <boost/units/io.hpp>
    #include <boost/units/systems/si.hpp>
    #include <boost/units/systems/si/io.hpp>
    
    #include <boost/date_time/posix_time/posix_time.hpp>
    namespace Time = boost::posix_time;
    
    typedef Time::ptime         DateTime;
    typedef Time::time_duration Duration;
    
    namespace Units {
        using namespace boost::units;
    
        namespace SI {
            using namespace boost::units::si;
        }
    
        template <class U> using Quantity = quantity<U>;
    
        typedef Quantity<SI::length>   Length;
        typedef Quantity<SI::velocity> Velocity;
        typedef Quantity<SI::time>     Time;
    } // namespace Units
    
    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/point_xy.hpp>
    struct MockLocation {
        boost::geometry::model::d2::point_xy<double> point;
    
        Units::Length distance(MockLocation const& other) const {
            return boost::geometry::distance(point, other.point) * 1000.0 * Units::SI::meter;
        }
    
        friend std::istream& operator>>(std::istream& is, MockLocation& ml) {
            double x,y;
            if (is >> x >> y)
                ml.point = {x,y};
            return is;
        }
    };
    
    #include <iostream>
    
    static inline DateTime operator+(DateTime const &lhs, Units::Time const &rhs) {
        return lhs + Time::seconds(rhs / Units::SI::second);
    }
    static inline DateTime operator-(DateTime const &lhs, Units::Time const &rhs) {
        return lhs - Time::seconds(rhs / Units::SI::second);
    }
    
    int main() try {
        MockLocation origin, destination;
        std::cin.exceptions(std::ios::failbit);
        std::cout << "Enter origin      x,y (km): "; std::cin >> origin;
        std::cout << "Enter destination x,y (km): "; std::cin >> destination;
    
        // a computation of distances which yields a length
        Units::Length distance = origin.distance(destination);
    
        Units::Velocity flight_speed(100 * Units::SI::meter / Units::SI::second);
    
        Units::Time flight_time = distance / flight_speed;
    
        DateTime departure_time = Time::second_clock::local_time();
    
        using Period = Time::time_period;
        std::cout 
            << "\nDistance " << distance 
            << " at " << flight_speed 
            << " Schedule: " << Period(departure_time, departure_time+flight_time) 
            << "\n";
    
    } catch(std::ios::failure const& e) {
        std::cerr << "Input error: " << e.what() << "\n";
    }
    

    Prints

    Enter origin      x,y (km): Enter destination x,y (km): 
    Distance 721110 m at 100 m s^-1 Schedule: [2018-Feb-23 14:22:55/2018-Feb-23 16:23:05.999999]