Add (subtract) months without exceeding the last day of the new month
The lubridate
function %m+%
may be useful here:
Add and subtract months to a date without exceeding the last day of the new month
as.Date("2014-12-31") %m+% months(6)
# [1] "2015-06-30"
To also handle the second case, you will need to round up to nearest month using ceiling_date
, and subtract one day using days
.
ceiling_date(as.Date("2014-02-28") %m+% months(6), unit = "month") - days(1)
# [1] "2014-08-31"
Subtracting months - issue with last day of month?
The lubridate
functions %m+%
and %m-%
are designed to handle this issue ("Add and subtract months to a date without exceeding the last day of the new month").
library(lubridate)
Sys.Date() %m-% months(18)
# [1] "2012-09-30"
# or to make it reproducible if Sys.Date() happens to be different from that in OP
as.Date("2014-03-31") %m-% months(18)
# [1] "2012-09-30"
# example of %m+%
as.Date("2014-01-31") + months(1)
# [1] NA
as.Date("2014-01-31") %m+% months(1)
# [1] "2014-02-28"
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"
Add a month to a Date
Vanilla R has a naive difftime class, but the Lubridate CRAN package lets you do what you ask:
require(lubridate)
d <- ymd(as.Date('2004-01-01')) %m+% months(1)
d
[1] "2004-02-01"
Hope that helps.
PHP DateTime::modify adding and subtracting months
Why it's not a bug:
The current behavior is correct. The following happens internally:
+1 month
increases the month number (originally 1) by one. This makes the date2010-02-31
.The second month (February) only has 28 days in 2010, so PHP auto-corrects this by just continuing to count days from February 1st. You then end up at March 3rd.
How to get what you want:
To get what you want is by: manually checking the next month. Then add the number of days next month has.
I hope you can yourself code this. I am just giving what-to-do.
PHP 5.3 way:
To obtain the correct behavior, you can use one of the PHP 5.3's new functionality that introduces the relative time stanza first day of
. This stanza can be used in combination with next month
, fifth month
or +8 months
to go to the first day of the specified month. Instead of +1 month
from what you're doing, you can use this code to get the first day of next month like this:
<?php
$d = new DateTime( '2010-01-31' );
$d->modify( 'first day of next month' );
echo $d->format( 'F' ), "\n";
?>
This script will correctly output February
. The following things happen when PHP processes this first day of next month
stanza:
next month
increases the month number (originally 1) by one. This makes the date 2010-02-31.first day of
sets the day number to1
, resulting in the date 2010-02-01.
Return datetime object of previous month
Try this:
def monthdelta(date, delta):
m, y = (date.month+delta) % 12, date.year + ((date.month)+delta-1) // 12
if not m: m = 12
d = min(date.day, [31,
29 if y%4==0 and (not y%100==0 or y%400 == 0) else 28,
31,30,31,30,31,31,30,31,30,31][m-1])
return date.replace(day=d,month=m, year=y)
>>> for m in range(-12, 12):
print(monthdelta(datetime.now(), m))
2009-08-06 16:12:27.823000
2009-09-06 16:12:27.855000
2009-10-06 16:12:27.870000
2009-11-06 16:12:27.870000
2009-12-06 16:12:27.870000
2010-01-06 16:12:27.870000
2010-02-06 16:12:27.870000
2010-03-06 16:12:27.886000
2010-04-06 16:12:27.886000
2010-05-06 16:12:27.886000
2010-06-06 16:12:27.886000
2010-07-06 16:12:27.886000
2010-08-06 16:12:27.901000
2010-09-06 16:12:27.901000
2010-10-06 16:12:27.901000
2010-11-06 16:12:27.901000
2010-12-06 16:12:27.901000
2011-01-06 16:12:27.917000
2011-02-06 16:12:27.917000
2011-03-06 16:12:27.917000
2011-04-06 16:12:27.917000
2011-05-06 16:12:27.917000
2011-06-06 16:12:27.933000
2011-07-06 16:12:27.933000
>>> monthdelta(datetime(2010,3,30), -1)
datetime.datetime(2010, 2, 28, 0, 0)
>>> monthdelta(datetime(2008,3,30), -1)
datetime.datetime(2008, 2, 29, 0, 0)
Edit Corrected to handle the day as well.
Edit See also the answer from puzzlement which points out a simpler calculation for d
:
d = min(date.day, calendar.monthrange(y, m)[1])
How to properly add 1 month from now to current date in moment.js
var currentDate = moment('2015-10-30');
var futureMonth = moment(currentDate).add(1, 'M');
var futureMonthEnd = moment(futureMonth).endOf('month');
if(currentDate.date() != futureMonth.date() && futureMonth.isSame(futureMonthEnd.format('YYYY-MM-DD'))) {
futureMonth = futureMonth.add(1, 'd');
}
console.log(currentDate);
console.log(futureMonth);
DEMO
EDIT
moment.addRealMonth = function addRealMonth(d) {
var fm = moment(d).add(1, 'M');
var fmEnd = moment(fm).endOf('month');
return d.date() != fm.date() && fm.isSame(fmEnd.format('YYYY-MM-DD')) ? fm.add(1, 'd') : fm;
}
var nextMonth = moment.addRealMonth(moment());
DEMO
How do I calculate the date in JavaScript three months prior to today?
var d = new Date();
d.setMonth(d.getMonth() - 3);
This works for January. Run this snippet:
var d = new Date("January 14, 2012");
console.log(d.toLocaleDateString());
d.setMonth(d.getMonth() - 3);
console.log(d.toLocaleDateString());
lubridate::floor_date returns NA
The clock package is really good for this, as it has an explicit argument specifying what you want done with invalid dates. And also the date_end function.
I think you want: (R >= 4.1 for native pipe)
library(clock)
start <- parse_date("2020-06-29")
n <- 8
start |> add_months(n, invalid = "previous") |> date_end('month')
Which gives:[1] "2021-02-28"
Related Topics
Conditionally Display a Block of Text in R Markdown
How to Tell Cran to Install Package Dependencies Automatically
Write List of Data.Frames to Separate CSV Files with Lapply
How to See Data from .Rdata File
What Does This Mean: Unable to Find an Inherited Method for Function 'A' for Signature '"B"'
Ggplot2: Adding Secondary Transformed X-Axis on Top of Plot
Setting Y Axis Breaks in Ggplot
Align Multiple Tables Side by Side
Data Table Merge Based on Date Ranges
Euclidean Distance of Two Vectors
Extract Last Word in String in R
Rgdal Installation Failed on Ubuntu 16.04
Libstdc++.So.6: Version 'Glibcxx_3.4.26' Not Found on Linux
Insert Blanks into a Vector For, E.G., Minor Tick Labels in R
Creating a Symmetric Matrix in R
Fill Region Between Two Loess-Smoothed Lines in R with Ggplot
R Function with No Return Value
How to Avoid: Read.Table Truncates Numeric Values Beginning with 0