1) Сначала определите начало месяца, som
и конец месяца, функции eom
, которые принимают объект класса Date
, строку даты в стандартном формате Date
или yearmon
возьмите и создайте объект класса Date
, дающий начало или конец года / месяца.
Используя их, создайте ежемесячный Date
ряд s
, используя начало каждого месяца месяца / год от from
до to
. Используйте pmax
, чтобы убедиться, что ряд не продолжается до from
и pmin
, чтобы он не продолжался после to
.
Входные аргументы могут быть строками в стандартном формате Date
, Date
объекты класса или yearmon
объекты класса. В случае yearmon
предполагается, что пользователь хотел получить полный месяц за каждый месяц. (Оператор if
может быть опущен, если вам не требуется поддержка yearmon
входов.)
library(zoo)
som <- function(x) as.Date(as.yearmon(x))
eom <- function(x) as.Date(as.yearmon(x), frac = 1)
date_ranges2 <- function(from, to) {
if (inherits(to, "yearmon")) to <- eom(to)
s <- seq(som(from), eom(to), "month")
data.frame(from = pmax(as.Date(from), s), to = pmin(as.Date(to), eom(s)))
}
date_ranges2("2000-01-10", "2000-06-20")
## from to
## 1 2000-01-10 2000-01-31
## 2 2000-02-01 2000-02-29
## 3 2000-03-01 2000-03-31
## 4 2000-04-01 2000-04-30
## 5 2000-05-01 2000-05-31
## 6 2000-06-01 2000-06-20
date_ranges2(as.yearmon("2000-01"), as.yearmon("2000-06"))
## from to
## 1 2000-01-01 2000-01-31
## 2 2000-02-01 2000-02-29
## 3 2000-03-01 2000-03-31
## 4 2000-04-01 2000-04-30
## 5 2000-05-01 2000-05-31
## 6 2000-06-01 2000-06-30
2) Эта альтернатива использует тот же подход, но определяет начало Месяц (som
) и конец месяца (eom
) работают без использования yearmon
, поэтому требуется только основание R. Он принимает символьные строки в стандартном формате Date
или входные данные класса Date
и выдает тот же результат, что и (1).
som <- function(x) as.Date(cut(as.Date(x), "month")) # start of month
eom <- function(x) som(som(x) + 32) - 1 # end of month
date_ranges3 <- function(from, to) {
s <- seq(som(from), as.Date(to), "month")
data.frame(from = pmax(as.Date(from), s), to = pmin(as.Date(to), eom(s)))
}
date_ranges3("2000-01-10", "2000-06-20")
## from to
## 1 2000-01-10 2000-01-31
## 2 2000-02-01 2000-02-29
## 3 2000-03-01 2000-03-31
## 4 2000-04-01 2000-04-30
## 5 2000-05-01 2000-05-31
## 6 2000-06-01 2000-06-20
date_ranges3(som("2000-01-10"), eom("2000-06-20"))
## from to
## 1 2000-01-01 2000-01-31
## 2 2000-02-01 2000-02-29
## 3 2000-03-01 2000-03-31
## 4 2000-04-01 2000-04-30
## 5 2000-05-01 2000-05-31
## 6 2000-06-01 2000-06-30