Obtenga la diferencia entre las fechas en términos de semanas, meses, trimestres y años

Tengo dos fechas digamos 14.01.2013 y 26.03.2014 .

Me gustaría obtener la diferencia entre esas dos fechas en términos de semanas (?), Meses (en el ejemplo 14), trimestres (4) y años (1).

¿Conoces la mejor manera de obtener esto?

    que tal esto?

     # get difference between dates `"01.12.2013"` and `"31.12.2013"` # weeks difftime(strptime("26.03.2014", format = "%d.%m.%Y"), strptime("14.01.2013", format = "%d.%m.%Y"),units="weeks") Time difference of 62.28571 weeks # months (as.yearmon(strptime("26.03.2014", format = "%d.%m.%Y"))- as.yearmon(strptime("14.01.2013", format = "%d.%m.%Y")))*12 [1] 14 # quarters (as.yearqtr(strptime("26.03.2014", format = "%d.%m.%Y"))- as.yearqtr(strptime("14.01.2013", format = "%d.%m.%Y")))*4 [1] 4 # years year(strptime("26.03.2014", format = "%d.%m.%Y"))- year(strptime("14.01.2013", format = "%d.%m.%Y")) [1] 1 

    as.yearmon() y as.yearqtr() están en el paquete zoo . year() está en paquete lubridate . ¿Qué piensas?

    Todas las respuestas existentes son imperfectas (OMI) y hacen suposiciones sobre el resultado deseado o no proporcionan flexibilidad para el resultado deseado.

    Con base en los ejemplos del PO, y las respuestas esperadas establecidas por el OP, creo que estas son las respuestas que está buscando (más algunos ejemplos adicionales que facilitan la extrapolación).

    (Esto solo requiere base R y no requiere zoológico o lubridate)

    Convertir a objetos de fecha y hora

     date_strings = c("14.01.2013", "26.03.2014") datetimes = strptime(date_strings, format = "%d.%m.%Y") # convert to datetime objects 

    Diferencia en días

    Puede usar la diferencia en días para obtener algunas de nuestras respuestas posteriores

     diff_in_days = difftime(datetimes[2], datetimes[1], units = "days") # days diff_in_days #Time difference of 435.9583 days 

    Diferencia en semanas

    La diferencia en semanas es un caso especial de units = "weeks" en difftime()

     diff_in_weeks = difftime(datetimes[2], datetimes[1], units = "weeks") # weeks diff_in_weeks #Time difference of 62.27976 weeks 

    Tenga en cuenta que esto es lo mismo que dividir nuestros diff_in_days entre 7 (7 días en una semana)

     as.double(diff_in_days)/7 #[1] 62.27976 

    Diferencia en años

    Con lógica similar, podemos derivar años de diff_in_days

     diff_in_years = as.double(diff_in_days)/365 # absolute years diff_in_years #[1] 1.194406 

    Parece que esperas que el diff en años sea “1”, así que supongo que solo quieres contar años calendario absolutos o algo así, lo cual puedes hacer fácilmente usando floor()

     # get desired output, given your definition of 'years' floor(diff_in_years) #[1] 1 

    Diferencia en cuartos

     # get desired output for quarters, given your definition of 'quarters' floor(diff_in_years * 4) #[1] 4 

    Diferencia en meses

    Puede calcular esto como una conversión de diff_years

     # months, defined as absolute calendar months (this might be what you want, given your question details) months_diff = diff_in_years*12 floor(month_diff) #[1] 14 

    Sé que esta pregunta es antigua, pero dado que todavía tenía que resolver este problema, creí que iba a agregar mis respuestas. Espero eso ayude.

    Durante semanas, puede usar la función difftime :

     date1 < - strptime("14.01.2013", format="%d.%m.%Y") date2 <- strptime("26.03.2014", format="%d.%m.%Y") difftime(date2,date1,units="weeks") Time difference of 62.28571 weeks 

    Pero difftime no funciona con la duración en semanas.
    La siguiente es una solución muy poco cut.POSIXt usa cut.POSIXt para esas duraciones, pero puede solucionarlo:

     seq1 < - seq(date1,date2, by="days") nlevels(cut(seq1,"months")) 15 nlevels(cut(seq1,"quarters")) 5 nlevels(cut(seq1,"years")) 2 

    Sin embargo, este es el número de meses, trimestres o años abarcados por su intervalo de tiempo y no la duración de su intervalo de tiempo expresado en meses, trimestres, años (ya que estos no tienen una duración constante). Considerando el comentario que hiciste sobre la respuesta de @SvenHohenstein, creo que puedes usar nlevels(cut(seq1,"months")) - 1 para lo que estás tratando de lograr.

    Acabo de escribir esto para otra pregunta, luego tropecé aquí.

     library(lubridate) #' Calculate age #' #' By default, calculates the typical "age in years", with a #' \code{floor} applied so that you are, eg, 5 years old from #' 5th birthday through the day before your 6th birthday. Set #' \code{floor = FALSE} to return decimal ages, and change \code{units} #' for units other than years. #' @param dob date-of-birth, the day to start calculating age. #' @param age.day the date on which age is to be calculated. #' @param units unit to measure age in. Defaults to \code{"years"}. Passed to \link{\code{duration}}. #' @param floor boolean for whether or not to floor the result. Defaults to \code{TRUE}. #' @return Age in \code{units}. Will be an integer if \code{floor = TRUE}. #' @examples #' my.dob < - as.Date('1983-10-20') #' age(my.dob) #' age(my.dob, units = "minutes") #' age(my.dob, floor = FALSE) age <- function(dob, age.day = today(), units = "years", floor = TRUE) { calc.age = interval(dob, age.day) / duration(num = 1, units = units) if (floor) return(as.integer(floor(calc.age))) return(calc.age) } 

    Ejemplos de uso:

     my.dob < - as.Date('1983-10-20') age(my.dob) # [1] 31 age(my.dob, floor = FALSE) # [1] 31.15616 age(my.dob, units = "minutes") # [1] 16375680 age(seq(my.dob, length.out = 6, by = "years")) # [1] 31 30 29 28 27 26 

    Aquí hay una solución:

     dates < - c("14.01.2013", "26.03.2014") # Date format: dates2 <- strptime(dates, format = "%d.%m.%Y") dif <- diff(as.numeric(dates2)) # difference in seconds dif/(60 * 60 * 24 * 7) # weeks [1] 62.28571 dif/(60 * 60 * 24 * 30) # months [1] 14.53333 dif/(60 * 60 * 24 * 30 * 3) # quartes [1] 4.844444 dif/(60 * 60 * 24 * 365) # years [1] 1.194521 

    prueba esto por una solución de meses

     StartDate < - strptime("14 January 2013", "%d %B %Y") EventDates <- strptime(c("26 March 2014"), "%d %B %Y") difftime(EventDates, StartDate) 

    Un cálculo más “preciso”. Es decir, el número de semana / mes / trimestre / año para una semana / mes / trimestre / año no completos es la fracción de días calendario en esa semana / mes / trimestre / año. Por ejemplo, la cantidad de meses entre 2016-02-22 y 2016-03-31 es 8/29 + 31/31 = 1.27586

    explicación en línea con el código

     #' Calculate precise number of periods between 2 dates #' #' @details The number of week/month/quarter/year for a non-complete week/month/quarter/year #' is the fraction of calendar days in that week/month/quarter/year. #' For example, the number of months between 2016-02-22 and 2016-03-31 #' is 8/29 + 31/31 = 1.27586 #' #' @param startdate start Date of the interval #' @param enddate end Date of the interval #' @param period character. It must be one of 'day', 'week', 'month', 'quarter' and 'year' #' #' @examples #' identical(numPeriods(as.Date("2016-02-15"), as.Date("2016-03-31"), "month"), 15/29 + 1) #' identical(numPeriods(as.Date("2016-02-15"), as.Date("2016-03-31"), "quarter"), (15 + 31)/(31 + 29 + 31)) #' identical(numPeriods(as.Date("2016-02-15"), as.Date("2016-03-31"), "year"), (15 + 31)/366) #' #' @return exact number of periods between #' numPeriods < - function(startdate, enddate, period) { numdays <- as.numeric(enddate - startdate) + 1 if (grepl("day", period, ignore.case=TRUE)) { return(numdays) } else if (grepl("week", period, ignore.case=TRUE)) { return(numdays / 7) } #create a sequence of dates between start and end dates effDaysinBins <- cut(seq(startdate, enddate, by="1 day"), period) #use the earliest start date of the previous bins and create a breaks of periodic dates with #user's period interval intervals <- seq(from=as.Date(min(levels(effDaysinBins)), "%Y-%m-%d"), by=paste("1",period), length.out=length(levels(effDaysinBins))+1) #create a sequence of dates between the earliest interval date and last date of the interval #that contains the enddate allDays <- seq(from=intervals[1], to=intervals[intervals > enddate][1] - 1, by="1 day") #bin all days in the whole period using previous breaks allDaysInBins < - cut(allDays, intervals) #calculate ratio of effective days to all days in whole period sum( tabulate(effDaysinBins) / tabulate(allDaysInBins) ) } #numPeriods 

    Avíseme si encuentra más casos límite donde la solución anterior no funciona.