2011-06-05 33 views
22

一個月的天數我在P上的日期找出R中

date = as.Date("2011-02-23", "%Y-%m-%d") 

是否有可能找出特定日期的月份的天數? (關於閏年)。在PHP它看起來與此類似(http://www.php.net/manual/en/function.date.php):

days = format(date, "%t") 

但「%T」似乎有R.不同的含義是否有一個解決這個問題?

回答

17

您可以編寫簡單的函數來做到這一點:

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"))) 
} 

調用爲:

> date = as.Date("2011-02-23", "%Y-%m-%d") 
> numberOfDays(date) 
[1] 28 
> date # date is unchanged 
[1] "2011-02-23" 
+0

如果通過的日期是本月的第一天,我不確定這是否有效。 – joran 2011-06-05 14:09:49

+0

不適用於載體......請查看我的方法 – Zafar 2017-09-16 01:24:00

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> 

as.numeric()將此轉換爲您可以使用的數字。

2

這基本上是德克的方法,但實際上放在一個函數中,以檢查下一個月是否也在下一年;並簡單地減去日期是一樣的使用difftime()

numberOfDays <- function(d){ 
    temp <- unlist(strsplit(as.character(d),"-")) 
    begin <- as.Date(paste(temp[1],temp[2],"01",sep="-")) 
    if (temp[2] != "12"){ 
     nextMonth <- as.character(as.integer(temp[2])+1) 
     end <- as.Date(paste(temp[1],nextMonth,"01",sep="-")) 
     return(as.integer(as.Date(end) - as.Date(begin))) 
    } 
    else{ 
     nextYear <- as.character(as.integer(temp[1])+1) 
     end <- as.Date(paste(nextYear,"01","01",sep="-")) 
     return(as.integer(as.Date(end) - as.Date(begin))) 
    } 
} 
12

這裏有兩個辦法。兩種方法都是矢量化的,即輸入x可以是一個單獨的"Date"類日期或這樣的日期的向量。

1)據此,輸入日期,x,成"yearmon"對象,然後將其轉換回至最後的月份和第一個月和減去2加法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 

或用於數字結果使用:

as.numeric(as.Date(ym, frac = 1) - as.Date(ym) + 1) 
## [1] 30 

1A)的變化將是:

as.Date(ym + 1/12) - as.Date(ym) 
## Time difference of 30 days 

或數字結果:

as.numeric(as.Date(ym + 1/12) - as.Date(ym)) 
## [1] 30 

2)這是一個鹼溶液中。首先我們定義fom,它輸入"Date"向量並返回每個組件的月份的第一個。現在我們只考慮下個月的第一天和本月的第一天之間的差異。

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

+1我不知道''的''frac' arg as.Date()' - 這是在哪裏記錄的?當我做'as.Date'時它不會顯示出來。 – 2011-06-05 23:14:56

+0

@Prasad,試試這個:'library(zoo); ?as.Date.yearmon'。 – 2011-06-06 00:51:00

7

這裏有一個簡單的辦法:在28:31n,發現導致有效日期的最大數量。在我的測試,這是快於任何的時間差爲基礎的方法至少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 

時序比較這裏建議:

> 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 
+2

如果只在上述示例中的某個日期執行此操作,則速度無關緊要,而如果某人在多個日期執行此操作,那麼'yearmon'方法會更快,因爲它已經進行了矢量化處理。嘗試計時'd < - Sys.Date()+ 1:100; sapply(d,ndays)'與'd < - Sys.Date()+ 1:100; ym < - as.yearmon(d); as.numeric(as.Date(ym,frac = 1) - as.Date(ym)+ 1)'在我的系統中,後者速度提高了5倍。也就是說,速度在任何情況下通常都不重要。 'yearmon'解決方案的簡單性似乎是更重要的優勢。 – 2011-06-05 21:17:47

+0

@ G.Grothendieck非常好的一點,我比較了時間,我同意你的看法。 – 2011-06-05 23:12:54

27

Hmisc library有幾個有用的功能,這樣做的:

require(Hmisc) 
monthDays(as.Date('2010-01-01')) 
1

你可以通過這一年,或在默認情況下采取本年度:

days.in.month = function(month, year = NULL){ 

    month = as.integer(month) 

    if (is.null(year)) 
    year = as.numeric(format(Sys.Date(), '%Y')) 

    dt = as.Date(paste(year, month, '01', sep = '-')) 
    dates = seq(dt, by = 'month', length = 2) 
    as.numeric(difftime(dates[2], dates[1], units = 'days')) 
} 
4

這是另一種可能的功能,不需要安裝任何軟件包。您只需爲該功能提供一個日期對象。因爲這裏還有很多其他優秀的答案我用眼睛寫邁向相當簡單,(希望)容易閱讀:)

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)) 
} 
+2

如果你進行跳躍檢查'y %% 4 == 0&(y %% 100!= 0 | y %% 400 == 0)',那麼它將一直工作。 – Gregor 2014-07-29 18:11:27

+0

非常好,謝謝你的提示。現在更新答案。 – 2014-07-29 18:17:27

+0

非常好的答案。 – 2016-05-13 14:09:19

2

我提供一個又一個班輪沒有額外的軟件包需要:

NumberOfDays <- function(date) 
return(as.numeric(format(as.Date(paste0(format(date,format="%Y"),formatC(ifelse(format(date,format="%m")=="12",0,as.numeric(format(date,format="%m")))+1,width=2,format="d",flag="0"),"01"),"%Y%m%d")-1,format="%d"))) 

> NumberOfDays(as.Date("2015-02-14","%Y-%m-%d")) 
[1] 28 

> system.time(NumberOfDays(as.Date("2015-02-14","%Y-%m-%d"))) 
    user  system  elapsed 
0.0010000000 0.0000000000 0.0009999999 

您應該使用您自己的首選項的格式爲此函數提供Date對象。

0

在另一種方式來獲得的日子可能是:

# Any date 
Today <- Sys.Date() 
# Get Month and Year 
Month <- format(Today,"%m") 
Year <- format(Today,"%Y") 
# get first date for the next month and then subtract 1 
Days <- format(
      as.Date( 
       paste0("01/",(as.numeric(Month)%%12)+1,"/",Year) 
       ,"%d/%m/%Y")-1,"%d") 
12

「Lubridate」軟件包所需的功能「days_in_month」關於leapyears。

你舉的例子:

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

閏年(2016):

> date_leap = as.Date("2016-02-23", "%Y-%m-%d") 
> days_in_month(date_leap) 
Feb 
29 
0

,我遲到了,但這個功能更好,並支持矢量:

month_days <- function(mon) { 
    # input as class "Date" 
    require(lubridate) 
    day(mon) <- 1 
    given <- mon 
    month(given) <- month(given) + 1 
    as.numeric(given - mon) 
} 
0
> Ymd<-"201602" 
> lastDate<-format(seq(as.POSIXct(sprintf("%s%s",substr(Ymd,1,6),"01"),format="%Y%m%d"),length=2,by="1 month")-1,"%Y%m%d")[2] 
> cat(as.integer(lastDate)%%100) 
29 
# Other Output 
> lastDate 
[1] "20160229" 
> cat(substr(lastDate,7,8)) 
29 
+0

只有代碼答案不能爲問題提供良好的解決方案。請嘗試解釋你所做的事情並添加信息。 – creyD 2018-02-01 13:44:49

0

這是另一種替代溶膠使用動物園的yearmon。 這是一個快速實用程序。

require(zoo) 
days_in_month <- function(d) { 
    rigor_days_in_month <- function(d) { 
     get_day <- function(x) as.numeric(format(x,"%d")) 
     m <- zoo::as.yearmon(d) 
     get_day(as.Date(m, frac = 1)) 
    } 
    mm <- as.numeric(format(d,"%m")) # get_month 
    ifelse(mm %in% c(1,3,5,7,8,10,12), 31, 
     ifelse(mm != 2, 30, 
      rigor_days_in_month(d))) 

} 

如果你願意,你可以解開get_day()使它成爲一行代碼。