找出R中一个月的天数

R_U*_*ser 28 r date

我在P有一个约会

 date = as.Date("2011-02-23", "%Y-%m-%d")
Run Code Online (Sandbox Code Playgroud)

是否有可能找出该特定日期的月份天数?(关于leapyears).在PHP中,它看起来与此类似(http://www.php.net/manual/en/function.date.php):

days = format(date, "%t")
Run Code Online (Sandbox Code Playgroud)

但是"%t"似乎在R中有不同的含义.这个问题是否有解决方案?

yon*_*oni 34

Hmisc库有几个这样做有用的功能:

require(Hmisc)
monthDays(as.Date('2010-01-01'))
Run Code Online (Sandbox Code Playgroud)


Geo*_*sky 23

"Lubridate"软件包需要关于suapyears的"days_in_month"函数.

你的例子:

> date = as.Date("2011-02-23", "%Y-%m-%d")
> days_in_month(date)
Feb
28
Run Code Online (Sandbox Code Playgroud)

闰年(2016年):

> date_leap = as.Date("2016-02-23", "%Y-%m-%d")
> days_in_month(date_leap)
Feb 
29 
Run Code Online (Sandbox Code Playgroud)


Grz*_*ski 21

你可以编写简单的函数来做到这一点:

numberOfDays <- function(date) {
    m <- format(date, format="%m")

    while (format(date, format="%m") == m) {
        date <- date + 1
    }

    return(as.integer(format(date - 1, format="%d")))
}
Run Code Online (Sandbox Code Playgroud)

调用为:

> date = as.Date("2011-02-23", "%Y-%m-%d")
> numberOfDays(date)
[1] 28
> date # date is unchanged
[1] "2011-02-23"
Run Code Online (Sandbox Code Playgroud)


Dir*_*tel 17

这就像在两个日期之间取得差异一样简单 - 所以将它作为本月的第一个月和下个月:

R> difftime( as.Date("2011-06-01"), as.Date("2011-05-01") )
Time difference of 31 days
R> as.numeric(difftime( as.Date("2011-06-01"), as.Date("2011-05-01") ))
[1] 31
R> 
Run Code Online (Sandbox Code Playgroud)

as.numeric()一个号码,您可以使用强制类型转换这一点.


G. *_*eck 12

这里有几种方法.两种方法都是矢量化的,即输入x可以是单个"Date"类日期或这些日期的矢量.

1)这将输入日期x转换为"yearmon"对象,然后将其转换回月份的最后一个月和第一个月,并减去两个加1.

x <- Sys.Date() # use today as the test date

library(zoo)
ym <- as.yearmon(x)
as.Date(ym, frac = 1) - as.Date(ym) + 1
## Time difference of 30 days
Run Code Online (Sandbox Code Playgroud)

或者使用数字结果:

as.numeric(as.Date(ym, frac = 1) - as.Date(ym) + 1)
## [1] 30
Run Code Online (Sandbox Code Playgroud)

1a)变化将是:

as.Date(ym + 1/12) - as.Date(ym)
## Time difference of 30 days
Run Code Online (Sandbox Code Playgroud)

或数字结果:

as.numeric(as.Date(ym + 1/12) - as.Date(ym))
## [1] 30
Run Code Online (Sandbox Code Playgroud)

2)这是一个基本解决方案.首先,我们定义fom哪个输入"Date"向量并返回每个组件的月份的第一个.现在我们只是考虑下个月的第一个月和当月的第一个月之间的差异.

fom <- function(x) as.Date(cut(x, "month"))
fom1 <- fom(x)
fom2 <- fom(fom1 +  32)
as.numeric(fom2 - fom1)
## [1] 30
Run Code Online (Sandbox Code Playgroud)


Pra*_*ani 7

这是一个简单的方法:对于nin 28:31,找到导致有效日期的最大数字.在我的测试中,这比任何基于时差的方法至少快4倍:

ndays <- function(d) {
  last_days <- 28:31
  rev(last_days[which(!is.na( 
                             as.Date( paste( substr(d, 1, 8), 
                                             last_days, sep = ''), 
                                      '%Y-%m-%d')))])[1]
}

> ndays('1999-03-10')
[1] 31
> ndays('1999-04-10')
[1] 30
> ndays('2000-02-10')
[1] 29
Run Code Online (Sandbox Code Playgroud)

与这里建议的一些其他方法进行时序比较:

> system.time( replicate( 5000, 
                          nd <- { 
   ym <- as.yearmon('2011-06-01'); 
   as.numeric( as.Date(ym, frac = 1) - as.Date(ym) + 1)
   }))

   user  system elapsed 
 16.634   1.807  18.238 

> system.time( replicate( 5000, 
               nd <- as.numeric( difftime( as.Date("2011-06-01"), 
                                           as.Date("2011-05-01") ))))
   user  system elapsed 
  3.137   0.341   3.470 

> system.time( replicate( 5000, nd <- ndays('2011-06-01')))
   user  system elapsed 
  0.729   0.044   0.771 
Run Code Online (Sandbox Code Playgroud)

  • 如果只在上面的例子中在一个日期做这个,那么速度是什么并不重要,而如果一个人在很多日期做这个,那么`yearmon`方法因为它已经被矢量化而更快.尝试计时`d < - Sys.Date()+ 1:100; sapply(d,ndays)`vs`d < - Sys.Date()+ 1:100; ym < - as.yearmon(d); as.numeric(as.Date(ym,frac = 1) - as.Date(ym)+ 1)`在我的系统上,后者快5倍.也就是说,速度在任何情况下通常都不重要.`yearmon`解决方案的简单性似乎是更重要的优势. (3认同)

Jac*_*mos 6

这是另一个可能的功能,不需要安装任何软件包.您只需为函数提供日期对象.由于这里有很多其他优秀的答案我写的是为了相当简单,(希望)易于阅读:)

daysInMonth <- function(d = Sys.Date()){

  m = substr((as.character(d)), 6, 7)              # month number as string
  y = as.numeric(substr((as.character(d)), 1, 4))  # year number as numeric

  # Quick check for leap year
  leap = 0
  if ((y %% 4 == 0 & y %% 100 != 0) | y %% 400 == 0)
    leap = 1

  # Return the number of days in the month
  return(switch(m,
                '01' = 31,
                '02' = 28 + leap,  # adds 1 if leap year
                '03' = 31,
                '04' = 30,
                '05' = 31,
                '06' = 30,
                '07' = 31,
                '08' = 31,
                '09' = 30,
                '10' = 31,
                '11' = 30,
                '12' = 31))
}
Run Code Online (Sandbox Code Playgroud)

  • 如果你进行跳跃检查`y %% 4 == 0&(y %% 100!= 0 | y %% 400 == 0)`那么它将始终有效. (2认同)