Skip to content

Commit

Permalink
Merge pull request #29 from eddelbuettel/feature/more_vectorisation
Browse files Browse the repository at this point in the history
updated toTz to be vectorised, additional test
  • Loading branch information
eddelbuettel committed Oct 9, 2018
2 parents 58516af + ebcb105 commit 4c76530
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 43 deletions.
10 changes: 10 additions & 0 deletions ChangeLog
@@ -1,3 +1,13 @@
2018-10-09 Dirk Eddelbuettel <edd@debian.org>

* DESCRIPTION (Version, Date): Roll minor version

* src/utilities.cpp (toTz): Vectorized toTz
* man/toTz.Rd: Updated documentation

* inst/unitTests/runit.Parse.R (test.Parse): Added test for
vectorised parse

2018-10-07 Dirk Eddelbuettel <edd@debian.org>

* DESCRIPTION (Version, Date): Roll minor version
Expand Down
4 changes: 2 additions & 2 deletions DESCRIPTION
@@ -1,8 +1,8 @@
Package: RcppCCTZ
Type: Package
Title: 'Rcpp' Bindings for the 'CCTZ' Library
Version: 0.2.4.1
Date: 2018-10-07
Version: 0.2.4.2
Date: 2018-10-09
Author: Dirk Eddelbuettel
Maintainer: Dirk Eddelbuettel <edd@debian.org>
Description: 'Rcpp' Access to the 'CCTZ' timezone library is provided. 'CCTZ' is
Expand Down
8 changes: 4 additions & 4 deletions R/RcppExports.R
Expand Up @@ -61,12 +61,12 @@ tzDiff <- function(tzfrom, tzto, dt, verbose = FALSE) {
#' a Datetime object from one given timezone to another.
#'
#' @title Shift datetime object from one timezone to another
#' @param dt A Datetime object specifying when the difference is to be computed.
#' @param dtv A DatetimeVector object specifying when the difference is to be computed.
#' @param tzfrom The first time zone as a character vector.
#' @param tzto The second time zone as a character vector.
#' @param verbose A boolean toggle indicating whether more verbose operations
#' are desired, default is \code{FALSE}.
#' @return A Datetime object with the given (civil time) determined by the
#' @return A DatetimeVector object with the given (civil time) determined by the
#' incoming object (and its timezone) shifted to the target timezone.
#' @author Dirk Eddelbuettel
#' @examples
Expand All @@ -80,8 +80,8 @@ tzDiff <- function(tzfrom, tzto, dt, verbose = FALSE) {
#' "America/New_York", "Australia/Sydney", verbose=TRUE),
#' tz="Australia/Sydney")
#' }
toTz <- function(dt, tzfrom, tzto, verbose = FALSE) {
.Call(`_RcppCCTZ_toTz`, dt, tzfrom, tzto, verbose)
toTz <- function(dtv, tzfrom, tzto, verbose = FALSE) {
.Call(`_RcppCCTZ_toTz`, dtv, tzfrom, tzto, verbose)
}

#' Format a Datetime vector
Expand Down
7 changes: 7 additions & 0 deletions inst/unitTests/runit.Parse.R
Expand Up @@ -38,5 +38,12 @@ test.Parse <- function() {
pt <- parseDouble("2010-01-02 03:04:05.123456", "%Y-%m-%d %H:%M:%E*S")
checkEquals(as.numeric(timepoint), pt[1,1], msg="parseDouble microsecs format")


timepoints <- ISOdatetime(2010,1,2,3,4,5, tz="UTC") + 0:9
tpvec <- format(timepoints)
ptvec <- parseDatetime(tpvec, "%Y-%m-%d %H:%M:%S", "UTC")
checkEquals(timepoints, ptvec, msg="vectorised parseDatetime")

options(digits.secs=ds)
}

6 changes: 3 additions & 3 deletions man/toTz.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions src/RcppExports.cpp
Expand Up @@ -86,16 +86,16 @@ BEGIN_RCPP
END_RCPP
}
// toTz
Rcpp::Datetime toTz(Rcpp::Datetime dt, const std::string tzfrom, const std::string tzto, bool verbose);
RcppExport SEXP _RcppCCTZ_toTz(SEXP dtSEXP, SEXP tzfromSEXP, SEXP tztoSEXP, SEXP verboseSEXP) {
Rcpp::DatetimeVector toTz(Rcpp::DatetimeVector dtv, const std::string tzfrom, const std::string tzto, bool verbose);
RcppExport SEXP _RcppCCTZ_toTz(SEXP dtvSEXP, SEXP tzfromSEXP, SEXP tztoSEXP, SEXP verboseSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< Rcpp::Datetime >::type dt(dtSEXP);
Rcpp::traits::input_parameter< Rcpp::DatetimeVector >::type dtv(dtvSEXP);
Rcpp::traits::input_parameter< const std::string >::type tzfrom(tzfromSEXP);
Rcpp::traits::input_parameter< const std::string >::type tzto(tztoSEXP);
Rcpp::traits::input_parameter< bool >::type verbose(verboseSEXP);
rcpp_result_gen = Rcpp::wrap(toTz(dt, tzfrom, tzto, verbose));
rcpp_result_gen = Rcpp::wrap(toTz(dtv, tzfrom, tzto, verbose));
return rcpp_result_gen;
END_RCPP
}
Expand Down
67 changes: 37 additions & 30 deletions src/utilities.cpp
Expand Up @@ -92,12 +92,12 @@ double tzDiffAtomic(const cctz::time_zone& tz1, const cctz::time_zone& tz2, cons
//' a Datetime object from one given timezone to another.
//'
//' @title Shift datetime object from one timezone to another
//' @param dt A Datetime object specifying when the difference is to be computed.
//' @param dtv A DatetimeVector object specifying when the difference is to be computed.
//' @param tzfrom The first time zone as a character vector.
//' @param tzto The second time zone as a character vector.
//' @param verbose A boolean toggle indicating whether more verbose operations
//' are desired, default is \code{FALSE}.
//' @return A Datetime object with the given (civil time) determined by the
//' @return A DatetimeVector object with the given (civil time) determined by the
//' incoming object (and its timezone) shifted to the target timezone.
//' @author Dirk Eddelbuettel
//' @examples
Expand All @@ -112,38 +112,45 @@ double tzDiffAtomic(const cctz::time_zone& tz1, const cctz::time_zone& tz2, cons
//' tz="Australia/Sydney")
//' }
// [[Rcpp::export]]
Rcpp::Datetime toTz(Rcpp::Datetime dt,
const std::string tzfrom,
const std::string tzto,
bool verbose=false) {
Rcpp::DatetimeVector toTz(Rcpp::DatetimeVector dtv,
const std::string tzfrom,
const std::string tzto,
bool verbose=false) {

// retain existing sub-second information
double remainder = dt.getFractionalTimestamp() - std::floor(dt.getFractionalTimestamp());
size_t n = dtv.size();
Rcpp::DatetimeVector rsv(n);
for (size_t i=0; i<n; i++) {
Rcpp::Datetime dt = dtv[i];

cctz::time_zone tz1, tz2; // two time zone objects
if (!cctz::load_time_zone(tzfrom, &tz1)) Rcpp::stop("Bad 'from' timezone");
if (!cctz::load_time_zone(tzto, &tz2)) Rcpp::stop("Bad 'to' timezone");

// incoming time-point object given civil-time and timezone
const auto tp = cctz::convert(cctz::civil_second(dt.getYear(),
dt.getMonth(),
dt.getDay(),
dt.getHours(),
dt.getMinutes(),
dt.getSeconds()),
tz1);
if (verbose) Rcpp::Rcout << cctz::format("%Y-%m-%d %H:%M:%S %z", tp, tz1) << std::endl;
if (verbose) Rcpp::Rcout << cctz::format("%Y-%m-%d %H:%M:%S %z", tp, tz2) << std::endl;

// create a civil-time object from time-point and new timezone
const auto ct = cctz::convert(tp, tz2);
if (verbose) Rcpp::Rcout << ct << std::endl;
// retain existing sub-second information
double remainder = dt.getFractionalTimestamp() - std::floor(dt.getFractionalTimestamp());

cctz::time_point<cctz::sys_seconds> ntp = cctz::convert(ct, tz2);
// time since epoch, with fractional seconds added back in
double newdt = ntp.time_since_epoch().count() + remainder;
cctz::time_zone tz1, tz2; // two time zone objects
if (!cctz::load_time_zone(tzfrom, &tz1)) Rcpp::stop("Bad 'from' timezone");
if (!cctz::load_time_zone(tzto, &tz2)) Rcpp::stop("Bad 'to' timezone");

return Rcpp::Datetime(newdt);
// incoming time-point object given civil-time and timezone
const auto tp = cctz::convert(cctz::civil_second(dt.getYear(),
dt.getMonth(),
dt.getDay(),
dt.getHours(),
dt.getMinutes(),
dt.getSeconds()),
tz1);
if (verbose) Rcpp::Rcout << cctz::format("%Y-%m-%d %H:%M:%S %z", tp, tz1) << std::endl;
if (verbose) Rcpp::Rcout << cctz::format("%Y-%m-%d %H:%M:%S %z", tp, tz2) << std::endl;

// create a civil-time object from time-point and new timezone
const auto ct = cctz::convert(tp, tz2);
if (verbose) Rcpp::Rcout << ct << std::endl;

cctz::time_point<cctz::sys_seconds> ntp = cctz::convert(ct, tz2);
// time since epoch, with fractional seconds added back in
double newdt = ntp.time_since_epoch().count() + remainder;
Rcpp::Datetime res = Rcpp::Datetime(newdt);
rsv[i] = res;
}
return rsv;
}


Expand Down

0 comments on commit 4c76530

Please sign in to comment.