2

Example

I have an Rcpp function where I would like to call boost::posix_time::time_from_string().

I've taken the example code from the boost documentation and translated it to a c++ function using Rcpp

library(Rcpp)

cppFunction(
  includes = '
    #include <boost/date_time/posix_time/posix_time.hpp>
  ',
  code = '
    void time_test() {
      std::string t = "2002-01-20 23:59:59.000";
      boost::posix_time::ptime pt(boost::posix_time::time_from_string(t));
      Rcpp::Rcout << "time from string: " << pt << std::endl;
    }
  ',
  depends = "BH"
)

However, this doesn't compile.

I've seen a few comments saying you need to link to -lboost_date_time, such as this line in Dirk's RcppBDT library

// The next function uses the non-stream-based parsing in Boost Date_Time
// and requires _linking_ with -lboost_date_time which makes the (otherwise
// header-only) build more complicate
// // [ [ Rcpp::export ] ]
// Rcpp::DatetimeVector charToPOSIXctNS(Rcpp::CharacterVector sv) {
//   ... code omitted ...
// }

Question

How do you provide the appropriate links to lboost_date_time, other than including the posix_time.hpp header, so that one can use time_from_string()?


Extra Info

It's possible to use other functions from the boost/date_time library, as demonstrated by this function, so what makes time_from_string() different?

cppFunction(
  includes = '
    #include <boost/date_time/posix_time/posix_time.hpp>
  ',
  code = '
    void time_test() {
      Rcpp::Datetime dt("2002-01-20 23:59:59.000");
      boost::posix_time::hours h( dt.getHours() );
      boost::posix_time::minutes m( dt.getMinutes() );
      boost::posix_time::seconds s( dt.getSeconds() );

      Rcpp::Rcout << h << std::endl;
      Rcpp::Rcout << m << std::endl;
      Rcpp::Rcout << s << std::endl;
    }
  ',
  depends = "BH"
)

time_test() 

# 12:00:00
# 00:59:00
# 00:00:59
SymbolixAU
  • 25,502
  • 4
  • 67
  • 139
  • See if my (old !!) `RcppBDT` -- which does a lot of stuff with Boost Date_Time -- or of course everybody's favourite converter `anytime` help. – Dirk Eddelbuettel Mar 13 '19 at 02:54
  • Oh, sorry, you may have missed the part where _string conversion / formatting with Boost requires linking_ which is why the two aforementioned packages do not do that. It's in the Boost Date_Time docs but somewhat hidden. To them linking is normal; to use with the benefit and portability of header-only it is not. – Dirk Eddelbuettel Mar 13 '19 at 02:56
  • In absence of a direct solution I'm actually using your [`stringToTime()`](https://github.com/eddelbuettel/anytime/blob/master/src/anytime.cpp#L199) function for now. (as I see you've bypassed `time_from_string()` in both `anytime` and `RcppBDT`) – SymbolixAU Mar 13 '19 at 02:57
  • You are free to use the Boost function _if and when you also link_. Easiest to wrap your head around in a five-line C++ program at the command-line. Not a constraint I impose. – Dirk Eddelbuettel Mar 13 '19 at 02:58

1 Answers1

4

As you already found out, you need to link with boost at the system level. The BH package is not sufficient. So first you have to install the required boost library. On Debian (dervied) Linux systems this can be done via

sudo apt-get install libboost-date-time-dev

Then you need to tell R to add -I/path/to/boost/headers and -L/path/to/boost/libraries -lboost_date_time to the compiler flags. You can do this by setting appropriate environment variables:

library(Rcpp)

Sys.setenv(PKG_LIBS="-L/usr/lib -lboost_date_time", PKG_CPPFLAGS="-I/usr/include")

cppFunction(
  includes = '
    #include <boost/date_time/posix_time/posix_time.hpp>
  ',
  code = '
    void time_test() {
      std::string t = "2002-01-20 23:59:59.000";
      boost::posix_time::ptime pt(boost::posix_time::time_from_string(t));
      Rcpp::Rcout << "time from string: " << pt << std::endl;
    }
  '
)

Notes:

  • One could also define a Rcpp plugin for this.
  • In my case -I... and -L... are unnecessary, since the library is installed in a standard location. One does need these flags in other cases, though.
Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75