[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