Reputation: 17537
Is there an easy way in R for me to itemize all valid days that occurred between two specified dates? For instance, I'd like the following inputs:
itemizeDates(startDate="12-30-11", endDate="1-4-12")
To produce the following dates:
"12-30-11" "12-31-11", "1-1-12", "1-2-12", "1-3-12", "1-4-12"
I'm flexible on classes and formatting of the dates, I just need an implementation of the concept.
Upvotes: 104
Views: 89707
Reputation: 18732
There are a few ways you can do this using the clock
package.
There is a sequencing function like many other answers, however with this function you have a finer control over the sequencing:
library(clock)
# every day between two dates
date_seq(from = Sys.Date(), to = Sys.Date() + 5, by = duration_days(1))
# [1] "2024-03-07" "2024-03-08" "2024-03-09" "2024-03-10" "2024-03-11" "2024-03-12"
# every other day between two dates
date_seq(from = Sys.Date(), to = Sys.Date() + 5, by = duration_days(2))
# [1] "2024-03-07" "2024-03-09" "2024-03-11"
# every 3rd month until total size is 3
# can do arithmetic in duration function and
# provide explicit resolution to invalid dates
date_seq(from = date_build(2024, 3, 31), by = duration_months(sqrt(9)),
total_size = 3, invalid = "previous-day")
# [1] "2024-03-31" "2024-06-30" "2024-09-30"
There is also a set of spanning functions that will span from the min and max of a vector:
x <- date_build(2024, c(3, 3, 3), c(7, 8, 11))
# [1] "2024-03-07" "2024-03-08" "2024-03-11"
# spans from min 2024-03-07 to max 2024-03-11
date_spanning_seq(x)
[1] "2024-03-07" "2024-03-08" "2024-03-09" "2024-03-10" "2024-03-11"
date_spanning_seq
uses day precision, so there is not as much control. calendar_spanning_seq
is available where you can provide more control over how to span.
Upvotes: 2
Reputation: 49820
You're looking for seq
> seq(as.Date("2011-12-30"), as.Date("2012-01-04"), by="days")
[1] "2011-12-30" "2011-12-31" "2012-01-01" "2012-01-02" "2012-01-03"
[6] "2012-01-04"
Or, you can use :
> as.Date(as.Date("2011-12-30"):as.Date("2012-01-04"), origin="1970-01-01")
[1] "2011-12-30" "2011-12-31" "2012-01-01" "2012-01-02" "2012-01-03"
[6] "2012-01-04"
Note that with :
"Non-numeric arguments are coerced internally". Thus, we convert back to class Date
, using as.Date
method for class 'numeric' and provide origin
.
Here's a function to meet your specific request
itemizeDates <- function(startDate="12-30-11", endDate="1-4-12",
format="%m-%d-%y") {
out <- seq(as.Date(startDate, format=format),
as.Date(endDate, format=format), by="days")
format(out, format)
}
> itemizeDates(startDate="12-30-11", endDate="1-4-12")
[1] "12-30-11" "12-31-11" "01-01-12" "01-02-12" "01-03-12" "01-04-12"
Upvotes: 166
Reputation: 1979
2 similar implementations in lubridate
:
library(lubridate)
as_date(mdy("12-30-11"):mdy("1-4-12"))
# OR
seq(mdy("12-30-11"), mdy("1-4-12"), by = "days")
These don't format your dates in month-day-year but you can fix the formatting if you want. But year-month-day is a bit easy to work with when analyzing.
Upvotes: 11
Reputation: 6116
I prefer using the lubridate package to solve datetime problems. It is more intuitive and easier to understand and use once you know it.
library(lubridate)
#mdy() in lubridate package means "month-day-year", which is used to convert
#the string to date object
>start_date <- mdy("12-30-11")
>end_date <- mdy("1-4-12")
#calculate how many days in this time interval
>n_days <- interval(start_date,end_date)/days(1)
>start_date + days(0:n_days)
[1]"2011-12-30" "2011-12-31" "2012-01-01" "2012-01-02" "2012-01-03" "2012-01-04"
#convert to original format
format(start_date + days(0:n_days), format="%m-%d-%y")
[1] "12-30-11" "12-31-11" "01-01-12" "01-02-12" "01-03-12" "01-04-12"
Reference: Dates and Times Made Easy with lubridate
Upvotes: 20