Welcome, guest | Sign In | My Account | Store | Cart
#include <boost/python.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <datetime.h> // compile with -I/path/to/python/include

/**
 * Convert boost::posix_ptime objects (ptime and time_duration)
 * to/from python datetime objects (datetime and timedelta).
 *
 * Credits:
 * http://libtorrent.svn.sourceforge.net/viewvc/libtorrent/trunk/bindings/python/src/datetime.cpp
 * http://www.nabble.com/boost::posix_time::ptime-conversion-td16857866.html
 */


static long get_usecs(boost::posix_time::time_duration const& d)
{
 
static long resolution
   
= boost::posix_time::time_duration::ticks_per_second();
 
long fracsecs = d.fractional_seconds();
 
if (resolution > 1000000)
   
return fracsecs / (resolution / 1000000);
 
else
   
return fracsecs * (1000000 / resolution);
}


/* Convert ptime to/from python */
struct ptime_to_python_datetime
{
   
static PyObject* convert(boost::posix_time::ptime const& pt)
   
{
        boost
::gregorian::date date = pt.date();
        boost
::posix_time::time_duration td = pt.time_of_day();
       
return PyDateTime_FromDateAndTime((int)date.year(),
                                         
(int)date.month(),
                                         
(int)date.day(),
                                          td
.hours(),
                                          td
.minutes(),
                                          td
.seconds(),
                                          get_usecs
(td));
   
}
};


struct ptime_from_python_datetime
{
     ptime_from_python_datetime
()
     
{
         boost
::python::converter::registry::push_back(
             
&convertible,
             
&construct,
             boost
::python::type_id<boost::posix_time::ptime > ());
     
}

     
static void* convertible(PyObject * obj_ptr)
     
{
       
if ( ! PyDateTime_Check(obj_ptr))
         
return 0;
       
return obj_ptr;
     
}

     
static void construct(
         
PyObject* obj_ptr,
         boost
::python::converter::rvalue_from_python_stage1_data * data)
     
{
       
PyDateTime_DateTime const* pydate
         
= reinterpret_cast<PyDateTime_DateTime*>(obj_ptr);

       
// Create date object
       boost
::gregorian::date _date(PyDateTime_GET_YEAR(pydate),
                                   
PyDateTime_GET_MONTH(pydate),
                                   
PyDateTime_GET_DAY(pydate));

       
// Create time duration object
       boost
::posix_time::time_duration
         _duration
(PyDateTime_DATE_GET_HOUR(pydate),
                   
PyDateTime_DATE_GET_MINUTE(pydate),
                   
PyDateTime_DATE_GET_SECOND(pydate),
                   
0);
       
// Set the usecs value
       _duration
+= boost::posix_time::microseconds(PyDateTime_DATE_GET_MICROSECOND(pydate));

       
// Create posix time object
       
void* storage = (
                       
(boost::python::converter::rvalue_from_python_storage<boost::posix_time::ptime>*)
                        data
)->storage.bytes;
       
new (storage)
         boost
::posix_time::ptime(_date, _duration);
       data
->convertible = storage;
     
}
};


/* Convert time_duration to/from python */
struct tduration_to_python_delta
{
   
static PyObject* convert(boost::posix_time::time_duration d)
   
{
     
long days = d.hours() / 24;
     
if (days < 0)
        days
--;
     
long seconds = d.total_seconds() - days*(24*3600);
     
long usecs = get_usecs(d);
     
if (days < 0)
        usecs
= 1000000-1 - usecs;
     
return PyDelta_FromDSU(days, seconds, usecs);
   
}
};


/* Should support the negative values, but not the special boost time
   durations */

struct tduration_from_python_delta
{
     tduration_from_python_delta
()
     
{
         boost
::python::converter::registry::push_back(
             
&convertible,
             
&construct,
             boost
::python::type_id<boost::posix_time::time_duration>());
     
}

     
static void* convertible(PyObject * obj_ptr)
     
{
       
if ( ! PyDelta_Check(obj_ptr))
         
return 0;
       
return obj_ptr;
     
}

     
static void construct(
         
PyObject* obj_ptr,
         boost
::python::converter::rvalue_from_python_stage1_data * data)
     
{
       
PyDateTime_Delta const* pydelta
         
= reinterpret_cast<PyDateTime_Delta*>(obj_ptr);

       
long days = pydelta->days;
       
bool is_negative = (days < 0);
       
if (is_negative)
         days
= -days;

       
// Create time duration object
       boost
::posix_time::time_duration
         duration
= boost::posix_time::hours(24)*days
                   
+ boost::posix_time::seconds(pydelta->seconds)
                   
+ boost::posix_time::microseconds(pydelta->microseconds);
       
if (is_negative)
         duration
= duration.invert_sign();

       
void* storage = (
                       
(boost::python::converter::rvalue_from_python_storage<boost::posix_time::time_duration>*)
                        data
)->storage.bytes;
       
new (storage)
         boost
::posix_time::time_duration(duration);
       data
->convertible = storage;
     
}
};

void bind_datetime()
{
   
PyDateTime_IMPORT;

    ptime_from_python_datetime
();

    to_python_converter
<
       
const boost::posix_time::ptime
     
, ptime_to_python_datetime
   
>();

    tduration_from_python_delta
();

    to_python_converter
<
       
const boost::posix_time::time_duration
     
, tduration_to_python_delta
   
>();
}

History

  • revision 10 (15 years ago)
  • previous revisions are not available