Número de meses entre dos fechas

¿Existe un método / fórmula estándar / común para calcular el número de meses entre dos fechas en R?

Estoy buscando algo que sea similar a la función de meses de MathWorks

    Estaba a punto de decir que es simple, pero difftime() detiene en semanas. Que extraño.

    Entonces, una respuesta posible sería piratear algo:

     # turn a date into a 'monthnumber' relative to an origin R> monnb < - function(d) { lt <- as.POSIXlt(as.Date(d, origin="1900-01-01")); \ lt$year*12 + lt$mon } # compute a month difference as a difference between two monnb's R> mondf < - function(d1, d2) { monnb(d2) - monnb(d1) } # take it for a spin R> mondf(as.Date("2008-01-01"), Sys.Date()) [1] 24 R> 

    Parece correcto. Uno podría envolver esto en una estructura de clase simple. O dejarlo como un truco 🙂

    Editar: También parece funcionar con tus ejemplos de Mathworks:

     R> mondf("2000-05-31", "2000-06-30") [1] 1 R> mondf(c("2002-03-31", "2002-04-30", "2002-05-31"), "2002-06-30") [1] 3 2 1 R> 

    Agregar el indicador EndOfMonth se deja como un ejercicio para el lector 🙂

    Edición 2: Tal vez el tiempo difftime lo difftime , ya que no existe una forma confiable de express la diferencia fraccional, lo que sería consistente con el comportamiento de otras unidades en el tiempo difftime .

    Una función simple …

     elapsed_months < - function(end_date, start_date) { ed <- as.POSIXlt(end_date) sd <- as.POSIXlt(start_date) 12 * (ed$year - sd$year) + (ed$mon - sd$mon) } 

    Ejemplo...

     >Sys.time() [1] "2014-10-29 15:45:44 CDT" >elapsed_months(Sys.time(), as.Date("2012-07-15")) [1] 27 >elapsed_months("2002-06-30", c("2002-03-31", "2002-04-30", "2002-05-31")) [1] 3 2 1 

    Para mí tiene sentido pensar en este problema simplemente restando dos fechas, y desde minuend − subtrahend = difference (wikipedia) , puse la fecha posterior primero en la lista de parámetros.

    Tenga en cuenta que funciona bien para las fechas anteriores a 1900 a pesar de las fechas que tienen representaciones internas del año como negativas, gracias a las reglas para restar números negativos ...

     > elapsed_months("1791-01-10", "1776-07-01") [1] 174 

    Puede haber una manera más simple. No es una función, pero es solo una línea.

     length(seq(from=date1, to=date2, by='month')) - 1 

    p.ej

     > length(seq(from=Sys.Date(), to=as.Date("2020-12-31"), by='month')) - 1 

    Produce:

     [1] 69 

    Esto calcula el número de meses enteros entre las dos fechas. Quite el -1 si desea incluir el mes / rest actual que no es un mes completo.

    Creo que esta es una respuesta más cercana a la pregunta formulada en términos de paridad con la función MathWorks

    Función de meses de MathWorks

     MyMonths = months(StartDate, EndDate, EndMonthFlag) 

    Mi código R

     library(lubridate) interval(mdy(10012015), today()) %/% months(1) 

    Salida (como cuando el código se ejecutó en abril de 2016)

     [1] 6 

    Lubridate [paquete] proporciona herramientas que facilitan el análisis y la manipulación de las fechas. Estas herramientas se agrupan a continuación por un propósito común. Se puede encontrar más información sobre cada función en su documentación de ayuda.

    interval {lubridate} crea un objeto Interval-class con las fechas de inicio y finalización especificadas. Si la fecha de inicio ocurre antes de la fecha de finalización, el intervalo será positivo. De lo contrario, será negativo

    hoy {lubridate} La fecha actual

    meses {Base} Extraer el mes Estas son funciones genéricas: los métodos para las clases internas de fecha y hora están documentados aquí.

    % /% {base} indica la división entera AKA (x% /% y) (hasta el error de redondeo)

    Hay un mensaje como el suyo en la lista de correo de R-Help (anteriormente mencioné una lista de CRAN).

    Aquí el enlace . Hay dos soluciones sugeridas:

    • Hay un promedio de 365.25 / 12 días por mes, por lo que la siguiente expresión indica el número de meses entre d1 y d2:
     #test data d1 < - as.Date("01 March 1950", "%d %B %Y") d2 <- as.Date(c("01 April 1955", "01 July 1980"), "%d %B %Y") # calculation round((d2 - d1)/(365.25/12)) 
    • Otra posibilidad es obtener la longitud de seq.Dates como este:
     as.Date.numeric < - function(x) structure(floor(x+.001), class = "Date") sapply(d2, function(d2) length(seq(d1, as.Date(d2), by = "month")))-1 
     library(lubridate) 

    case1: función ingenua

     mos< -function (begin, end) { mos1<-as.period(interval(ymd(begin),ymd(end))) mos<-mos1@year*12+mos1@month mos } 

    caso2: si necesita considerar solo 'Mes' independientemente de 'Día'

     mob< -function (begin, end) { begin<-paste(substr(begin,1,6),"01",sep="") end<-paste(substr(end,1,6),"01",sep="") mob1<-as.period(interval(ymd(begin),ymd(end))) mob<-mob1@year*12+mob1@month mob } 

    Ejemplo:

     mos(20150101,20150228) # 1 mos(20150131,20150228) # 0 # you can use "20150101" instead of 20150101 mob(20150131,20150228) # 1 mob(20150131,20150228) # 1 # you can use a format of "20150101", 20150101, 201501 
     library(lubridate) date1 = "1 April 1977" date2 = "7 July 2017" date1 = dmy(date1) date2 = dmy(date2) number_of_months = (year(date1) - year(date2)) * 12 + month(date1) - month(date2) 

    Diferencia en meses = 12 * diferencia en años + diferencia en meses.

    Es posible que sea necesario corregir lo siguiente con la condición ifelse para las restas del mes