Generate a Sequence of the Last Day of the Month Over Two Years

Generate a sequence of the last day of the month over two years

Yes, you found the correct trick: going back a day from the first of the next month.

Here is as a one-liner in base R:

R> seq(as.Date("2010-02-01"), length=24, by="1 month") - 1
[1] "2010-01-31" "2010-02-28" "2010-03-31" "2010-04-30" "2010-05-31"
[6] "2010-06-30" "2010-07-31" "2010-08-31" "2010-09-30" "2010-10-31"
[11] "2010-11-30" "2010-12-31" "2011-01-31" "2011-02-28" "2011-03-31"
[16] "2011-04-30" "2011-05-31" "2011-06-30" "2011-07-31" "2011-08-31"
[21] "2011-09-30" "2011-10-31" "2011-11-30" "2011-12-31"
R>

So no need for lubridate which (while being a fine package) isn't needed for simple task like this. Plus, its overloading of existing base functions still strikes me as somewhat dangerous...

generate a date sequence of last day of month in R

This gives a sequence of end-of-month dates from the year/month of st to the year/month of en.

library(zoo)
as.Date(seq(as.yearmon(st), as.yearmon(en), by = 1 / freq), frac = 1)

In the above st and en could be any class that converts to yearmon including yearmon itself, Date, character strings or numeric. For example, "2000-02-01", "2000-02", as.Date("2000-02-01"), 2000+1/12.

If en is a date and the end date of the sequence should be no later than en then replace as.yearmon(en) with the following which subtracts 1/12 if en is not at the end of the month.

as.yearmon(en) - (as.Date(en) < as.Date(as.yearmon(en), frac = 1)) / 12

Similarly if st is a date and the starting date of the sequence should be no later than st use the same idea to subtract 1/12 if st is not at the end of the month replacing as.yearmon(st) with

as.yearmon(st) - (as.Date(st) < as.Date(as.yearmon(st), frac = 1)) / 12

There is some question regarding whether we really need dates at all since they are always at the end of the month. It seems that the point is to create a year/month sequence and the end-of-month dates are just a way to represent that.
A simpler way would be this yearmon sequence directly.

seq(as.yearmon(st), as.yearmon(en), by = 1 / freq)

find last day of month in a sequence of dates

Try:

which(ave(as.numeric(ds),format(ds,"%Y%m"),FUN=function(x) x==max(x))==1)

Generate date sequence by months

I think this is most elegantly solved by taking the day of the month component out of the equation while you are generating the sequence. With the clock package, you can generate a month precision sequence, then easily set the day to the last day of the month.

library(clock)

start <- as.Date("2014-03-31")
end <- as.Date("2021-09-30")

start <- calendar_narrow(as_year_month_day(start), "month")
end <- calendar_narrow(as_year_month_day(end), "month")

# Month precision dates
start
#> <year_month_day<month>[1]>
#> [1] "2014-03"
end
#> <year_month_day<month>[1]>
#> [1] "2021-09"

seq(start, end, by = 3) |>
set_day("last") |>
as.Date()
#> [1] "2014-03-31" "2014-06-30" "2014-09-30" "2014-12-31" "2015-03-31"
#> [6] "2015-06-30" "2015-09-30" "2015-12-31" "2016-03-31" "2016-06-30"
#> [11] "2016-09-30" "2016-12-31" "2017-03-31" "2017-06-30" "2017-09-30"
#> [16] "2017-12-31" "2018-03-31" "2018-06-30" "2018-09-30" "2018-12-31"
#> [21] "2019-03-31" "2019-06-30" "2019-09-30" "2019-12-31" "2020-03-31"
#> [26] "2020-06-30" "2020-09-30" "2020-12-31" "2021-03-31" "2021-06-30"
#> [31] "2021-09-30"

Created on 2022-08-15 by the reprex package (v2.0.1)

Create sequence of date on every last day of month

If you want last day of month, instead of start from 2018-01-31, try

seq(as.Date("2018-02-01",format="%Y-%m-%d"),by="month",length.out=6) -1
[1] "2018-01-31" "2018-02-28" "2018-03-31" "2018-04-30" "2018-05-31" "2018-06-30"

Sequence of dates by each next 15th or last day of month

start <- as.Date("2014-05-03")
end <- as.Date("2014-07-01")

library(lubridate)
floor_date(seq(start, end, by = 'month'), unit = "month") + 14
ceiling_date(seq(start, end, by = 'month'), unit = "month")-1

Sequence by the month and use floor_date from the lubridate package to start at the beginning of the month.

create sequence of months and days with no year

We can create a date sequence (any year would work, no need to be 2001 in my example), and then use the format function.

format(seq.Date(as.Date("2001-10-31"), as.Date("2001-12-31"), by = 1),
format = "%m-%d")
# [1] "10-31" "11-01" "11-02" "11-03" "11-04" "11-05" "11-06" "11-07" "11-08" "11-09" "11-10"
# [12] "11-11" "11-12" "11-13" "11-14" "11-15" "11-16" "11-17" "11-18" "11-19" "11-20" "11-21"
# [23] "11-22" "11-23" "11-24" "11-25" "11-26" "11-27" "11-28" "11-29" "11-30" "12-01" "12-02"
# [34] "12-03" "12-04" "12-05" "12-06" "12-07" "12-08" "12-09" "12-10" "12-11" "12-12" "12-13"
# [45] "12-14" "12-15" "12-16" "12-17" "12-18" "12-19" "12-20" "12-21" "12-22" "12-23" "12-24"
# [56] "12-25" "12-26" "12-27" "12-28" "12-29" "12-30" "12-31"

sequence of monthly dates making sure it's the same day, or the last day of month in case of invalid

The simplest solution is %m+% from lubridate, which solves this exact problem. So:

seq_monthly <- function(from,length.out) {
return(from %m+% months(c(0:(length.out-1))))
}

Output:

> seq_monthly(as.Date("2015-01-31"),length.out=4)
[1] "2015-01-31" "2015-02-28" "2015-03-31" "2015-04-30"

Create end of the month date from a date variable

To get the end of months you could just create a Date vector containing the 1st of all the subsequent months and subtract 1 day.

date.end.month <- seq(as.Date("2012-02-01"),length=4,by="months")-1
date.end.month
[1] "2012-01-31" "2012-02-29" "2012-03-31" "2012-04-30"


Related Topics



Leave a reply



Submit