Chapter 16 Date and DateVector

Date is a scalar type corresponding to an element of DateVector (but see the DateVector subsetting section below for a potential pitfall).

16.1 Creating Date objects

Date d;       //"1970-01-01"
Date d(1);    //"1970-01-01" + 1 day
Date d(1.1);  //"1970-01-01" + ceil(1.1) day
Date( "2000-01-01", "%Y-%m-%d"); //default format is "%Y-%m-%d"
Date( 1, 2, 2000); // 2000-01-02 Date(mon, day, year)
Date( 2000, 1, 2); // 2000-01-02 Date(year, mon, day)

16.2 Operators

Date has operators +, -, <, >, >=, <=, ==, !=. By using these operators, you can perform addition of days (+), difference calculation of date (-), and comparison of dates (<, <=, >, >=, ==, !=) .

// [[Rcpp::export]]
DateVector rcpp_date1(){
    // Creating Date objects
    Date d1("2000-01-01");
    Date d2("2000-02-01");

    int  i  = d2 - d1; // difference of dates
    bool b  = d2 > d1; // comparison of dates

    Rcout << i << "\n"; // 31
    Rcout << b << "\n"; // 1


    DateVector date(1);
    date[0] = d1 + 1;  // adding 1 day to d1

    return date; // 2000-01-02
}

Note: As mentioned above, the - operator is used for calculating the difference between dates, not subtraction. If you want to subtract a number of days from a Date you can add a negative number.

// [[Rcpp::export]]
Date subtract_day() {
    Date d1("2000-01-01");
    
    // This causes a compiler error
    // Date d2 = d1 - 1;
    
    // This subtracts a day
    Date d2 = d1 + -1;
    
    return d2;  // 1999-12-31
}

16.3 Member functions

16.3.1 format()

Returns the date as a std::string using the same specification as base R (see the documentation for strptime or run help(format.Date)). The default format is “YYYY-MM-DD”.

16.3.2 getDay()

Returns the day of the date.

16.3.3 getMonth()

Returns the month of the date.

16.3.4 getYear()

Returns the year of the date.

16.3.5 getWeekday()

Returns the day of the week as an int. (1:Sun 2:Mon 3:Tue 4:Wed 5:Thu 6:Sat)

16.3.6 getYearday()

Returns the number of the date through the year with January 1st as 1 and December 31st as 365.

16.3.7 is_na()

Returns true if this object is NA.

16.4 Execution result

Date d("2016-1-1");
Rcout << d.format("%d/%m/%Y") << endl;  // "1/1/2016"
Rcout << d.getDay() << endl;            // 1
Rcout << d.getMonth() << endl;          // 1
Rcout << d.getYear() << endl;           // 2016
Rcout << d.getWeekday() << endl;        // 6
Rcout << d.getYearday() << endl;        // 1

16.5 DateVector subsetting

Internally, both DateVector and DateTimeVector are stored as numeric types. This can cause confusion when subsetting a DateVector with [], as the item extracted is a double, not a Date as you might assume. For example, the code below looks logical but fails to compile because dates[i] (a double) has no getYear() method.

// [[Rcpp::export]]
void print_years(DateVector dates) {
    for (auto i = 0; i < dates.length(); i++) {
        Rcout << dates[i].getYear() << std::endl;
    }
}

Here’s the compiler error (edited for brevity):

E> error: request for member 'getYear' in '[...]' which is of non-class type 'const type {aka const double}'
E>      Rcout << dates[i].getYear() << std::endl;
E>                        ^

To make this work you can explicitly create a Date object from dates[i]:

// [[Rcpp::export]]
void print_years(DateVector dates) {
    for (auto i = 0; i < dates.length(); i++) {
        Date d = dates[i];    // Create a `Date`
        Rcout << d.getYear() << std::endl;
    }
}

As mentioned in this StackOverflow question, if you actually want a std::vector<Date> you can use the DateVector.getDates() method.