Rcpp Version 0.12.12
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  ~Date() {};
71 
72  double getDate(void) const {
73  return m_d;
74  }
75 
76  // intra-day useless for date class
77  //int getSeconds() const { return m_tm.tm_sec; }
78  //int getMinutes() const { return m_tm.tm_min; }
79  //int getHours() const { return m_tm.tm_hour; }
80  int getDay() const { return m_tm.tm_mday; }
81  int getMonth() const { return m_tm.tm_mon + 1; } // makes it 1 .. 12
82  int getYear() const { return m_tm.tm_year; } // does include 1900 (see Date.cpp)
83  int getWeekday() const { return m_tm.tm_wday + 1; } // makes it 1 .. 7
84  int getYearday() const { return m_tm.tm_yday + 1; } // makes it 1 .. 366
85 
86  // 1900 as per POSIX mktime() et al
87  static inline unsigned int baseYear() {
88  return 1900;
89  }
90 
91  // Minimal set of date operations.
92  friend Date operator+( const Date &date, int offset);
93  friend double 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  friend bool operator<=(const Date &date1, const Date& date2);
99  friend bool operator!=(const Date &date1, const Date& date2);
100 
101  inline int is_na() const {
102  return traits::is_na<REALSXP>(m_d);
103  }
104 
105  operator double() const {
106  return m_d;
107  }
108 
109  inline std::string format(const char *fmt = "%Y-%m-%d") const {
110  char txt[32];
111  struct tm temp = m_tm;
112  temp.tm_year -= baseYear(); // adjust for fact that system has year rel. to 1900
113  size_t res = ::strftime(txt, 31, fmt, &temp);
114  if (res == 0) {
115  return std::string("");
116  } else {
117  return std::string(txt);
118  }
119  }
120 
121  friend inline std::ostream &operator<<(std::ostream & os, const Date d);
122 
123  private:
124  double m_d; // (fractional) day number, relative to epoch of Jan 1, 1970
125  struct tm m_tm; // standard time representation
126 
127  // update m_tm based on m_d
128  void update_tm() {
129  if (R_FINITE(m_d)) {
130  time_t t = static_cast<time_t>(24*60*60 * m_d); // (fractional) days since epoch to seconds since epoch
131  m_tm = *gmtime_(&t);
132  } else {
133  m_tm.tm_sec = m_tm.tm_min = m_tm.tm_hour = m_tm.tm_isdst = NA_INTEGER;
134  m_tm.tm_min = m_tm.tm_hour = m_tm.tm_mday = m_tm.tm_mon = m_tm.tm_year = NA_INTEGER;
135  }
136  }
137 
138  };
139 
140  // template specialisation for wrap() on the date
141  template <> SEXP wrap<Rcpp::Date>(const Rcpp::Date &date);
142 
143  // needed to wrap containers of Date such as vector<Date> or map<string,Date>
144  namespace internal {
145  template<> inline double caster<Rcpp::Date,double>(Rcpp::Date from) {
146  return static_cast<double>(from.getDate());
147  }
148  template<> inline Rcpp::Date caster<double,Rcpp::Date>(double from) {
149  return Rcpp::Date(static_cast<int>(from));
150  }
151  }
152 
153  template<> inline SEXP wrap_extra_steps<Rcpp::Date>(SEXP x) {
154  Rf_setAttrib(x, R_ClassSymbol, Rf_mkString("Date"));
155  return x;
156  }
157 
158  inline Date operator+(const Date &date, int offset) {
159  Date newdate(date.m_d);
160  newdate.m_d += offset;
161  time_t t = static_cast<time_t>(24*60*60 * newdate.m_d); // days since epoch to seconds since epo
162  newdate.m_tm = *gmtime_(&t);
163  return newdate;
164  }
165 
166  inline double 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  inline bool operator<=(const Date &d1, const Date& d2) { return d1.m_d <= d2.m_d; }
172  inline bool operator!=(const Date &d1, const Date& d2) { return d1.m_d != d2.m_d; }
173 
174  inline std::ostream &operator<<(std::ostream & os, const Date d) {
175  os << d.format();
176  return os;
177  }
178 
179  namespace internal {
180 
181  inline SEXP getPosixClasses() {
182  Shield<SEXP> datetimeclass(Rf_allocVector(STRSXP,2));
183  SET_STRING_ELT(datetimeclass, 0, Rf_mkChar("POSIXct"));
184  SET_STRING_ELT(datetimeclass, 1, Rf_mkChar("POSIXt"));
185  return datetimeclass;
186  }
187 
188  inline SEXP new_posixt_object( double d) {
189  Shield<SEXP> x(Rf_ScalarReal(d));
190  Rf_setAttrib(x, R_ClassSymbol, getPosixClasses());
191  return x;
192  }
193 
194  inline SEXP new_date_object(double d) {
195  Shield<SEXP> x(Rf_ScalarReal(d));
196  Rf_setAttrib(x, R_ClassSymbol, Rf_mkString("Date"));
197  return x;
198  }
199 
200  }
201 
202 
203 }
204 
205 #endif
SEXP new_posixt_object(double d)
Definition: Date.h:188
friend bool operator<=(const Date &date1, const Date &date2)
Definition: Date.h:171
std::string format(const char *fmt="%Y-%m-%d") const
Definition: Date.h:109
attribute_hidden double mktime00(struct tm &tm)
Definition: routines.h:104
int getYear() const
Definition: Date.h:82
friend bool operator==(const Date &date1, const Date &date2)
Definition: Date.h:169
Date(const unsigned int &mon, const unsigned int &day, const unsigned int &year)
Definition: Date.h:52
~Date()
Definition: Date.h:70
void update_tm()
Definition: Date.h:128
double m_d
Definition: Date.h:124
friend Date operator+(const Date &date, int offset)
Definition: Date.h:158
friend bool operator<(const Date &date1, const Date &date2)
Definition: Date.h:167
Date(const int &dt)
Definition: Date.h:40
int is_na() const
Definition: Date.h:101
double getDate(void) const
Definition: Date.h:72
bool is_na< REALSXP >(double x)
Definition: is_na.h:41
SEXP getPosixClasses()
Definition: Date.h:181
friend std::ostream & operator<<(std::ostream &os, const Date d)
Definition: Date.h:174
SEXP new_date_object(double d)
Definition: Date.h:194
Date(const double &dt)
Definition: Date.h:46
int getYearday() const
Definition: Date.h:84
friend bool operator>=(const Date &date1, const Date &date2)
Definition: Date.h:170
struct tm m_tm
Definition: Date.h:125
int getWeekday() const
Definition: Date.h:83
friend bool operator!=(const Date &date1, const Date &date2)
Definition: Date.h:172
attribute_hidden struct tm * gmtime_(const time_t *const x)
Definition: routines.h:110
double dt(double x, double n, int lg)
Definition: Rmath.h:90
friend double operator-(const Date &date1, const Date &date2)
Definition: Date.h:166
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:87
int getDay() const
Definition: Date.h:80
friend bool operator>(const Date &date1, const Date &date2)
Definition: Date.h:168
int getMonth() const
Definition: Date.h:81