Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

date

r

lubridate

I use lubridate and figured that this would be so easy

ymd("2010-01-31")+months(0:23) 

But look what one gets. It is all messed up!

 [1] "2010-01-31 UTC" "2010-03-03 UTC" "2010-03-31 UTC" "2010-05-01 UTC" "2010-05-31 UTC" "2010-07-01 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-10-01 UTC" [10] "2010-10-31 UTC" "2010-12-01 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-03-03 UTC" "2011-03-31 UTC" "2011-05-01 UTC" "2011-05-31 UTC" "2011-07-01 UTC" [19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-10-01 UTC" "2011-10-31 UTC" "2011-12-01 UTC" "2011-12-31 UTC" 

Then I read how lubridate caters to phenomenon such as interval, duration and period. So, OK I realize that a month is actually the number of days defined by (365*4+1)/48 = 30.438 days. So I tried to get smart and rewrite it as

ymd("2010-01-31")+ as.period(months(0:23)) 

But that just gave an error.

Error in as.period.default(months(0:23)) :    (list) object cannot be coerced to type 'double' 
like image 988
Farrel Avatar asked Nov 30 '11 22:11

Farrel


2 Answers

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...

like image 172
Dirk Eddelbuettel Avatar answered Sep 19 '22 19:09

Dirk Eddelbuettel


It is amazing how typing out a question focuses creative energy. I think I worked out the answer. I may as well post it here for the next poor soul who finds themselves wasting time.

ymd("2010-02-01")+ months(0:23)-days(1) 

Simply specify the first day of the next month and generate a sequence from that but subtract 1 days from it to get the last day of the preceding month.

[1] "2010-01-31 UTC" "2010-02-28 UTC" "2010-03-31 UTC" "2010-04-30 UTC" "2010-05-31 UTC" "2010-06-30 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-09-30 UTC" [10] "2010-10-31 UTC" "2010-11-30 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-02-28 UTC" "2011-03-31 UTC" "2011-04-30 UTC" "2011-05-31 UTC" "2011-06-30 UTC" [19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-09-30 UTC" "2011-10-31 UTC" "2011-11-30 UTC" "2011-12-31 UTC" 

By the way, how do I get rid of the pesky "UTC" designations. Time zones are a life saver when they are needed. The rest of the time they are a nuisance.

like image 41
Farrel Avatar answered Sep 19 '22 19:09

Farrel