[Rcpp-commits] r1677 - in pkg/Rcpp: inst inst/include/Rcpp src
noreply at r-forge.r-project.org
noreply at r-forge.r-project.org
Wed Jun 23 19:35:38 CEST 2010
Author: edd
Date: 2010-06-23 19:35:38 +0200 (Wed, 23 Jun 2010)
New Revision: 1677
Modified:
pkg/Rcpp/inst/ChangeLog
pkg/Rcpp/inst/include/Rcpp/Date.h
pkg/Rcpp/src/Date.cpp
Log:
use mktime00() from R's src/main/datetime.c for an always-GMT version of mktime()
Modified: pkg/Rcpp/inst/ChangeLog
===================================================================
--- pkg/Rcpp/inst/ChangeLog 2010-06-23 17:21:44 UTC (rev 1676)
+++ pkg/Rcpp/inst/ChangeLog 2010-06-23 17:35:38 UTC (rev 1677)
@@ -1,3 +1,8 @@
+2010-06-23 Dirk Eddelbuettel <edd at debian.org>
+
+ * src/Date.cpp: Import mktime00() from R's src/main/datetime.c
+ * inst/include/Rcpp/Date.h: Add mktime00() declaration
+
2010-06-23 Romain Francois <romain at r-enthusiasts.com>
* inst/include/Rcpp/Date_forward.h: forward declaration of Rcpp::Date and
Modified: pkg/Rcpp/inst/include/Rcpp/Date.h
===================================================================
--- pkg/Rcpp/inst/include/Rcpp/Date.h 2010-06-23 17:21:44 UTC (rev 1676)
+++ pkg/Rcpp/inst/include/Rcpp/Date.h 2010-06-23 17:35:38 UTC (rev 1677)
@@ -1,4 +1,4 @@
-// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
+// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 4 -*-
//
// Date.h: Rcpp R/C++ interface class library -- dates
//
@@ -28,47 +28,49 @@
class Date {
public:
- Date();
- Date(const int &dt); // from integer, just like R (with negative dates before Jan 1, 1970)
- Date(const std::string &s, const std::string &fmt="%Y-%m-%d");
- Date(const unsigned int &m, const unsigned int &d, const unsigned int &y);
- ~Date();
+ Date();
+ Date(const int &dt); // from integer, just like R (with negative dates before Jan 1, 1970)
+ Date(const std::string &s, const std::string &fmt="%Y-%m-%d");
+ Date(const unsigned int &m, const unsigned int &d, const unsigned int &y);
+ ~Date();
- int getDate(void) const;
+ int getDate(void) const;
#if 0
- // rest to follow
- // assignment
- // copy
- // ...
-
- // Minimal set of date operations.
- friend Date operator+(const Date &date, int offset);
- friend int operator-(const Date& date1, const Date& date2);
- friend bool operator<(const Date &date1, const Date& date2);
- friend bool operator>(const Date &date1, const Date& date2);
- friend bool operator==(const Date &date1, const Date& date2);
- friend bool operator>=(const Date &date1, const Date& date2);
- friend bool operator<=(const Date &date1, const Date& date2);
+ // rest to follow
+ // assignment
+ // copy
+ // ...
+
+ // Minimal set of date operations.
+ friend Date operator+(const Date &date, int offset);
+ friend int operator-(const Date& date1, const Date& date2);
+ friend bool operator<(const Date &date1, const Date& date2);
+ friend bool operator>(const Date &date1, const Date& date2);
+ friend bool operator==(const Date &date1, const Date& date2);
+ friend bool operator>=(const Date &date1, const Date& date2);
+ friend bool operator<=(const Date &date1, const Date& date2);
#endif
private:
int d; // day number, relative to epoch of Jan 1, 1970
+
+ double mktime00(struct tm &tm) const; // from R's src/main/datetime.c
+
};
// template specialisation for wrap() on the date
template <> SEXP wrap<Rcpp::Date>(const Rcpp::Date &date);
- // needed to wrap containers of Date such as vector<Date>
- // or map<string,Date>
- namespace internal{
- template<> inline double caster<Rcpp::Date,double>( Rcpp::Date from){
- return static_cast<double>( from.getDate() ) ;
- }
- template<> inline Rcpp::Date caster<double,Rcpp::Date>( double from){
- return Rcpp::Date( static_cast<int>( from ) ) ;
- }
+ // needed to wrap containers of Date such as vector<Date> or map<string,Date>
+ namespace internal {
+ template<> inline double caster<Rcpp::Date,double>( Rcpp::Date from){
+ return static_cast<double>( from.getDate() ) ;
+ }
+ template<> inline Rcpp::Date caster<double,Rcpp::Date>( double from){
+ return Rcpp::Date( static_cast<int>( from ) ) ;
+ }
}
template<> inline SEXP wrap_extra_steps<Rcpp::Date>( SEXP x ){
Modified: pkg/Rcpp/src/Date.cpp
===================================================================
--- pkg/Rcpp/src/Date.cpp 2010-06-23 17:21:44 UTC (rev 1676)
+++ pkg/Rcpp/src/Date.cpp 2010-06-23 17:35:38 UTC (rev 1677)
@@ -53,7 +53,7 @@
tm.tm_mon = mon - 1; // range 0 to 11
tm.tm_year = year - 1900;
}
- double tmp = mktime(&tm);
+ double tmp = mktime00(tm); // use R's internal mktime() replacement
d = tmp/(24*60*60);
}
@@ -66,6 +66,51 @@
};
+ // Taken from R's src/main/datetime.c and made a member function called with C++ reference
+ /* Substitute for mktime -- no checking, always in GMT */
+ double Date::mktime00(struct tm &tm) const {
+
+ static const int days_in_month[12] =
+ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+ #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
+ #define days_in_year(year) (isleap(year) ? 366 : 365)
+
+ int day = 0;
+ int i, year, year0;
+ double excess = 0.0;
+
+ day = tm.tm_mday - 1;
+ year0 = 1900 + tm.tm_year;
+ /* safety check for unbounded loops */
+ if (year0 > 3000) {
+ excess = (int)(year0/2000) - 1;
+ year0 -= excess * 2000;
+ } else if (year0 < 0) {
+ excess = -1 - (int)(-year0/2000);
+ year0 -= excess * 2000;
+ }
+
+ for(i = 0; i < tm.tm_mon; i++) day += days_in_month[i];
+ if (tm.tm_mon > 1 && isleap(year0)) day++;
+ tm.tm_yday = day;
+
+ if (year0 > 1970) {
+ for (year = 1970; year < year0; year++)
+ day += days_in_year(year);
+ } else if (year0 < 1970) {
+ for (year = 1969; year >= year0; year--)
+ day -= days_in_year(year);
+ }
+
+ /* weekday: Epoch day was a Thursday */
+ if ((tm.tm_wday = (day + 4) % 7) < 0) tm.tm_wday += 7;
+
+ return tm.tm_sec + (tm.tm_min * 60) + (tm.tm_hour * 3600)
+ + (day + excess * 730485) * 86400.0;
+ }
+
+
template <> SEXP wrap(const Date &date) {
SEXP value = PROTECT(Rf_allocVector(REALSXP, 1));
REAL(value)[0] = date.getDate();
More information about the Rcpp-commits
mailing list