Rcpp Version 1.0.0
Date.h
Go to the documentation of this file.
1 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*-
2 //
3 // Date.h: Rcpp R/C++ interface class library -- dates
4 //
5 // Copyright (C) 2010 - 2015 Dirk Eddelbuettel and Romain Francois
6 //
7 // This file is part of Rcpp.
8 //
9 // Rcpp is free software: you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // Rcpp is distributed in the hope that it will be useful, but
15 // WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Rcpp. If not, see <http://www.gnu.org/licenses/>.
21 
22 #ifndef Rcpp__Date_h
23 #define Rcpp__Date_h
24 
25 #if defined(WIN32) || defined(__WIN32) || defined(__WIN32__)
26 #include <time.h>
27 #endif
28 
29 namespace Rcpp {
30 
31  class Date {
32  public:
33  Date() {
34  m_d = 0;
35  update_tm();
36  }
37  Date(SEXP s);
38 
39  // from integer (with negative dates before Jan 1, 1970)
40  Date(const int &dt) {
41  m_d = dt;
42  update_tm();
43  }
44 
45  // from fractional integer since epoch, just like R
46  Date(const double &dt) {
47  m_d = dt;
48  update_tm();
49  }
50  Date(const std::string &s, const std::string &fmt="%Y-%m-%d");
51 
52  Date(const unsigned int &mon, const unsigned int &day, const unsigned int &year) {
53  m_tm.tm_sec = m_tm.tm_min = m_tm.tm_hour = m_tm.tm_isdst = 0;
54 
55  // allow for ISO-notation case (yyyy, mm, dd) which we prefer over (mm, dd, year)
56  if (mon >= baseYear() && day <= 12 && year <= 31) {
57  m_tm.tm_year = mon - baseYear();
58  m_tm.tm_mon = day - 1; // range 0 to 11
59  m_tm.tm_mday = year;
60  } else {
61  m_tm.tm_mday = day;
62  m_tm.tm_mon = mon - 1; // range 0 to 11
63  m_tm.tm_year = year - baseYear();
64  }
65  double tmp = mktime00(m_tm); // use mktime() replacement borrowed from R
66  m_tm.tm_year += baseYear(); // we'd rather keep it as a normal year
67  m_d = tmp/(24*60*60);
68  }
69 
70  double getDate(void) const {
71  return m_d;
72  }
73 
74  // intra-day useless for date class
75  //int getSeconds() const { return m_tm.tm_sec; }
76  //int getMinutes() const { return m_tm.tm_min; }
77  //int getHours() const { return m_tm.tm_hour; }
78  int getDay() const { return m_tm.tm_mday; }
79  int getMonth() const { return m_tm.tm_mon + 1; } // makes it 1 .. 12
80  int getYear() const { return m_tm.tm_year; } // does include 1900 (see Date.cpp)
81  int getWeekday() const { return m_tm.tm_wday + 1; } // makes it 1 .. 7
82  int getYearday() const { return m_tm.tm_yday + 1; } // makes it 1 .. 366
83 
84  // 1900 as per POSIX mktime() et al
85  static inline unsigned int baseYear() {
86  return 1900;
87  }
88 
89  // Minimal set of date operations.
90  friend Date operator+( const Date &date, int offset);
91  friend double operator-( const Date &date1, const Date& date2);
92  friend bool operator<( const Date &date1, const Date& date2);
93  friend bool operator>( const Date &date1, const Date& date2);
94  friend bool operator==(const Date &date1, const Date& date2);
95  friend bool operator>=(const Date &date1, const Date& date2);
96  friend bool operator<=(const Date &date1, const Date& date2);
97  friend bool operator!=(const Date &date1, const Date& date2);
98 
99  inline int is_na() const {
100  return traits::is_na<REALSXP>(m_d);
101  }
102 
103  operator double() const {
104  return m_d;
105  }
106 
107  inline std::string format(const char *fmt = "%Y-%m-%d") const {
108  char txt[32];
109  struct tm temp = m_tm;
110  temp.tm_year -= baseYear(); // adjust for fact that system has year rel. to 1900
111  size_t res = ::strftime(txt, 31, fmt, &temp);
112  if (res == 0) {
113  return std::string("");
114  } else {
115  return std::string(txt);
116  }
117  }
118 
119  friend inline std::ostream &operator<<(std::ostream & os, const Date d);
120 
121  private:
122  double m_d; // (fractional) day number, relative to epoch of Jan 1, 1970
123  struct tm m_tm; // standard time representation
124 
125  // update m_tm based on m_d
126  void update_tm() {
127  if (R_FINITE(m_d)) {
128  time_t t = static_cast<time_t>(24*60*60 * m_d); // (fractional) days since epoch to seconds since epoch
129  m_tm = *gmtime_(&t);
130  } else {
131  m_tm.tm_sec = m_tm.tm_min = m_tm.tm_hour = m_tm.tm_isdst = NA_INTEGER;
132  m_tm.tm_min = m_tm.tm_hour = m_tm.tm_mday = m_tm.tm_mon = m_tm.tm_year = NA_INTEGER;
133  }
134  }
135 
136  };
137 
138  // template specialisation for wrap() on the date
139  template <> SEXP wrap<Rcpp::Date>(const Rcpp::Date &date);
140 
141  // needed to wrap containers of Date such as vector<Date> or map<string,Date>
142  namespace internal {
143  template<> inline double caster<Rcpp::Date,double>(Rcpp::Date from) {
144  return static_cast<double>(from.getDate());
145  }
146  template<> inline Rcpp::Date caster<double,Rcpp::Date>(double from) {
147  return Rcpp::Date(static_cast<int>(from));
148  }
149  }
150 
151  template<> inline SEXP wrap_extra_steps<Rcpp::Date>(SEXP x) {
152  Rf_setAttrib(x, R_ClassSymbol, Rf_mkString("Date"));
153  return x;
154  }
155 
156  inline Date operator+(const Date &date, int offset) {
157  Date newdate(date.m_d);
158  newdate.m_d += offset;
159  time_t t = static_cast<time_t>(24*60*60 * newdate.m_d); // days since epoch to seconds since epo
160  newdate.m_tm = *gmtime_(&t);
161  return newdate;
162  }
163 
164  inline double operator-( const Date& d1, const Date& d2) { return d1.m_d - d2.m_d; }
165  inline bool operator<( const Date &d1, const Date& d2) { return d1.m_d < d2.m_d; }
166  inline bool operator>( const Date &d1, const Date& d2) { return d1.m_d > d2.m_d; }
167  inline bool operator==(const Date &d1, const Date& d2) { return d1.m_d == d2.m_d; }
168  inline bool operator>=(const Date &d1, const Date& d2) { return d1.m_d >= d2.m_d; }
169  inline bool operator<=(const Date &d1, const Date& d2) { return d1.m_d <= d2.m_d; }
170  inline bool operator!=(const Date &d1, const Date& d2) { return d1.m_d != d2.m_d; }
171 
172  inline std::ostream &operator<<(std::ostream & os, const Date d) {
173  os << d.format();
174  return os;
175  }
176 
177  namespace internal {
178 
179  inline SEXP getPosixClasses() {
180  Shield<SEXP> datetimeclass(Rf_allocVector(STRSXP,2));
181  SET_STRING_ELT(datetimeclass, 0, Rf_mkChar("POSIXct"));
182  SET_STRING_ELT(datetimeclass, 1, Rf_mkChar("POSIXt"));
183  return datetimeclass;
184  }
185 
186  inline SEXP new_posixt_object( double d) {
187  Shield<SEXP> x(Rf_ScalarReal(d));
188  Rf_setAttrib(x, R_ClassSymbol, getPosixClasses());
189  return x;
190  }
191 
192  inline SEXP new_date_object(double d) {
193  Shield<SEXP> x(Rf_ScalarReal(d));
194  Rf_setAttrib(x, R_ClassSymbol, Rf_mkString("Date"));
195  return x;
196  }
197 
198  }
199 
200 
201 }
202 
203 #endif
SEXP new_posixt_object(double d)
Definition: Date.h:186
friend bool operator<=(const Date &date1, const Date &date2)
Definition: Date.h:169
attribute_hidden double mktime00(struct tm &tm)
Definition: routines.h:118
int is_na() const
Definition: Date.h:99
friend bool operator==(const Date &date1, const Date &date2)
Definition: Date.h:167
Date(const unsigned int &mon, const unsigned int &day, const unsigned int &year)
Definition: Date.h:52
int getYear() const
Definition: Date.h:80
void update_tm()
Definition: Date.h:126
double m_d
Definition: Date.h:122
friend Date operator+(const Date &date, int offset)
Definition: Date.h:156
friend bool operator<(const Date &date1, const Date &date2)
Definition: Date.h:165
Date(const int &dt)
Definition: Date.h:40
bool is_na< REALSXP >(double x)
Definition: is_na.h:42
SEXP getPosixClasses()
Definition: Date.h:179
friend std::ostream & operator<<(std::ostream &os, const Date d)
Definition: Date.h:172
SEXP new_date_object(double d)
Definition: Date.h:192
Date(const double &dt)
Definition: Date.h:46
friend bool operator>=(const Date &date1, const Date &date2)
Definition: Date.h:168
int getWeekday() const
Definition: Date.h:81
struct tm m_tm
Definition: Date.h:123
double getDate(void) const
Definition: Date.h:70
int getDay() const
Definition: Date.h:78
friend bool operator!=(const Date &date1, const Date &date2)
Definition: Date.h:170
attribute_hidden struct tm * gmtime_(const time_t *const x)
Definition: routines.h:124
double dt(double x, double n, int lg)
Definition: Rmath.h:90
friend double operator-(const Date &date1, const Date &date2)
Definition: Date.h:164
int getYearday() const
Definition: Date.h:82
Rcpp API.
Definition: algo.h:28
static struct tm tm
Definition: Date.cpp:437
Date()
Definition: Date.h:33
static unsigned int baseYear()
Definition: Date.h:85
int getMonth() const
Definition: Date.h:79
friend bool operator>(const Date &date1, const Date &date2)
Definition: Date.h:166
std::string format(const char *fmt="%Y-%m-%d") const
Definition: Date.h:107