我有两个约会,我们说14.01.2013
和26.03.2014
。
我想根据周(?),月(在示例14中),季度(4)和年(1)来区分这两个日期。
你知道最好的方法吗?
答案 0 :(得分:63)
怎么样:
# 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()
和as.yearqtr()
位于包zoo
中。 year()
位于lubridate
个包中。
你觉得怎么样?
答案 1 :(得分:37)
所有现有答案都不完善(IMO),要么对所需输出做出假设,要么不为所需输出提供灵活性。
基于OP中的示例以及OP所述的预期答案,我认为这些是您正在寻找的答案(以及一些可以轻松推断的其他示例)。
(这只需要基础R,并且不需要动物园或劳动力)
转换为日期时间对象
date_strings = c("14.01.2013", "26.03.2014")
datetimes = strptime(date_strings, format = "%d.%m.%Y") # convert to datetime objects
天数差异
您可以在几天内使用差异来获得我们以后的一些答案
diff_in_days = difftime(datetimes[2], datetimes[1], units = "days") # days
diff_in_days
#Time difference of 435.9583 days
周差异
周差异是units = "weeks"
difftime()
的一个特例
diff_in_weeks = difftime(datetimes[2], datetimes[1], units = "weeks") # weeks
diff_in_weeks
#Time difference of 62.27976 weeks
请注意,这与将diff_in_days除以7(一周7天)相同
as.double(diff_in_days)/7
#[1] 62.27976
年份差异
使用类似的逻辑,我们可以从diff_in_days
中获得数年diff_in_years = as.double(diff_in_days)/365 # absolute years
diff_in_years
#[1] 1.194406
你似乎期待多年来的差异是" 1"所以我假设你只想计算绝对日历年或其他东西,你可以使用floor()
<轻松做到/ p>
# get desired output, given your definition of 'years'
floor(diff_in_years)
#[1] 1
季度差异
# get desired output for quarters, given your definition of 'quarters'
floor(diff_in_years * 4)
#[1] 4
月份差异
可以将其计算为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
我知道这个问题已经过时了,但考虑到我现在仍然需要解决这个问题,我想我会加上答案。希望能帮助到你。
答案 2 :(得分:13)
几周后,您可以使用函数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
但是difftime
在持续数周内不起作用
以下是使用cut.POSIXt
进行持续时间的非常不理想的解决方案,但您可以解决此问题:
seq1 <- seq(date1,date2, by="days")
nlevels(cut(seq1,"months"))
15
nlevels(cut(seq1,"quarters"))
5
nlevels(cut(seq1,"years"))
2
然而,这是您的时间间隔跨越的月数,季度或年数,而不是您的时间间隔的持续时间,以月,季度,年为单位(因为那些没有恒定的持续时间)。考虑到你对@SvenHohenstein做出的评论,我认为你可以使用nlevels(cut(seq1,"months")) - 1
来实现你想要实现的目标。
答案 3 :(得分:12)
我刚刚写了另一个问题,然后在这里跌跌撞撞。
library(lubridate)
#' Calculate age
#'
#' By default, calculates the typical "age in years", with a
#' \code{floor} applied so that you are, e.g., 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)
}
用法示例:
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
答案 4 :(得分:3)
这是一个解决方案:
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
答案 5 :(得分:1)
更“精确”的计算。也就是说,非完整周/月/季度/年的周/月/季/年数是该周/月/季/年中的日历天数的百分比。例如,2016-02-22和2016-03-31之间的月数是8/29 + 31/31 = 1.27586
内联代码
的解释#' 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
如果您发现上述解决方案不起作用的更多边界情况,请告诉我。
答案 6 :(得分:1)
日期是这里的大话题,给出的答案也很棒。此处仍是出色的lubridate
答案(尽管@Gregor的功能正在使用此程序包)
lubridate timespan documentation对于理解时段和持续时间之间的差异非常有帮助。我也喜欢lubridate cheatsheet和this very useful thread
library(lubridate)
dates <- c(dmy('14.01.2013'),dmy('26.03.2014'))
span <- dates[1] %--% dates[2] #creating an interval object
#creating period objects
as.period(span, unit = 'year')
#> [1] "1y 2m 12d 0H 0M 0S"
as.period(span, unit = 'month')
#> [1] "14m 12d 0H 0M 0S"
as.period(span, unit = 'day')
#> [1] "436d 0H 0M 0S"
期间不接受以周为单位。但是您可以将持续时间转换为星期:
as.duration(span)/ dweeks(1)
#makes duration object (in seconds) and divides by duration of a week (in seconds)
#> [1] 62.28571
由reprex package(v0.3.0)于2019-11-04创建
答案 7 :(得分:1)
这是一种通过 lubridate 包找出年份差异的简单方法:
as.numeric(as.Date("14-03-2013", format = "%d-%m-%Y") %--% as.Date("23-03-2014", format = "%d-%m-%Y"), "年")
这将返回 1.023956 如果您不想要小数,可以使用 floor()。
答案 8 :(得分:0)
尝试一个月的解决方案
StartDate <- strptime("14 January 2013", "%d %B %Y")
EventDates <- strptime(c("26 March 2014"), "%d %B %Y")
difftime(EventDates, StartDate)