87

I'm trying to build folders to store data pulls. I want to label the folders with the day of that data in the pull.

Ex. I pull 5 days ago data from mysql i want to name the folder the date from 5 days ago.

MySQL can easily handle date arithmetic. I'm not sure exactly how R does it. Should i just subtract the appropriate number of seconds in POSIXct and then convert to POSIXlt to name the folder MM_DD_YYYY?

Or is there a better way?

Jaap
  • 81,064
  • 34
  • 182
  • 193
Dan
  • 6,008
  • 7
  • 40
  • 41

3 Answers3

118

Just subtract a number:

> as.Date("2009-10-01")
[1] "2009-10-01"
> as.Date("2009-10-01")-5
[1] "2009-09-26"

Since the Date class only has days, you can just do basic arithmetic on it.

If you want to use POSIXlt for some reason, then you can use it's slots:

> a <- as.POSIXlt("2009-10-04")
> names(unclass(as.POSIXlt("2009-10-04")))
[1] "sec"   "min"   "hour"  "mday"  "mon"   "year"  "wday"  "yday"  "isdst"
> a$mday <- a$mday - 6
> a
[1] "2009-09-28 EDT"
Shane
  • 98,550
  • 35
  • 224
  • 217
  • 1
    Or use POSIXct and subtract a day's worth of seconds. `trunc()` and `round()` are also useful for trimming POSIXt objects. – Sharpie Feb 13 '10 at 03:29
  • ok that looks like the best so far. And just to be sure it handles different month day amounts and leap years correctly? – Dan Feb 14 '10 at 22:43
  • Yes, it does all of those things correctly. You can do a quick test yourself by setting the date to be around DST (for instance) to confirm this as each approach can have different behavior. – Shane Feb 22 '10 at 20:49
  • Also, the R documentation states that $yday is only informational and cannot be used for incrementing the date. – Robert Casey Oct 08 '14 at 23:51
  • and use `format` along with `as.Date` depending on your needs, eg `as.Date('15/02/2015', format('%d/%m/%Y'))+ 21` – tagoma Jan 02 '16 at 15:27
61

The answer probably depends on what format your date is in, but here is an example using the Date class:

dt <- as.Date("2010/02/10")
new.dt <- dt - as.difftime(2, unit="days")

You can even play with different units like weeks.

m0nhawk
  • 22,980
  • 9
  • 45
  • 73
Aniko
  • 18,516
  • 4
  • 48
  • 45
  • 9
    Valid units for as.difftime are: "secs", "mins", "hours", "days", "weeks". – jbaums Jun 10 '11 at 01:06
  • In my opinion, this is the best answer, since it works with POSIXct and POSIXlt fields without discarding time information while being base R. While the answer says it _probably depends on what format your date is in_ it seems to work fine with all valid date formats in base R. – Erik A Feb 14 '22 at 15:16
48

There is of course a lubridate solution for this:

library(lubridate)
date <- "2009-10-01"

ymd(date) - 5
# [1] "2009-09-26"

is the same as

ymd(date) - days(5)
# [1] "2009-09-26"

Other time formats could be:

ymd(date) - months(5)
# [1] "2009-05-01"

ymd(date) - years(5)
# [1] "2004-10-01"

ymd(date) - years(1) - months(2) - days(3)
# [1] "2008-07-29"
J_F
  • 9,956
  • 2
  • 31
  • 55
  • 3
    For people commonly using dates, the lubridate library is the most intuitive option. – JASC May 18 '19 at 23:04
  • 1
    Definitely try the %m+% (and %m-%) operator to add (substract) one month to January 31th without breaking anything. – feinmann Mar 01 '20 at 22:29