楚新元 | All in R

Welcome to R Square

用 R 计算一年有多少天?

楚新元 / 2023-10-17


这个问题本质上就是判断给定年份是否为闰年,计算逻辑其实很简单:年份能被 4 整除、但不能被 100 整除,或能被 400 整除的年份为闰年,其余为平年;闰年 2 月份是 29 天,全年 366 年,平年 2 月份是 28 天,全年 365 天。我之所以会遇到这个问题是因为我在写 CNID 包的时候遇到了一个要判断身份证号码是否符合逻辑的问题。我写的代码有点啰嗦,感谢谢益辉亲自操刀在评论区给出了优雅、简洁且支持向量化的代码。

编写函数

# 判断闰年
leap_year = function(year) {
  (year %% 4 == 0 & year %% 100 != 0) | (year %% 400 == 0)
}

# 计算一年有多少天
ydays = function(year) {
  365 + leap_year(year)
}

# 计算某年某月有多少天
mdays = function(year, month) {
  days = c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month]
  days[month == 2 & leap_year(year)] = 29  # 闰年的二月为 29 天
  days
}

# 年月组合
mdays_df = function(year, month) {
  df = expand.grid(year = year, month = month)
  cbind(df, days = do.call(mdays, as.list(df)))
}

实战测试

leap_year(2020:2024)
#> [1]  TRUE FALSE FALSE FALSE  TRUE
ydays(2020:2024)
#> [1] 366 365 365 365 366
mdays(2024, 1:12)
#>  [1] 31 29 31 30 31 30 31 31 30 31 30 31
mdays_df(2020:2024, 1:4)
#>    year month days
#> 1  2020     1   31
#> 2  2021     1   31
#> 3  2022     1   31
#> 4  2023     1   31
#> 5  2024     1   31
#> 6  2020     2   29
#> 7  2021     2   28
#> 8  2022     2   28
#> 9  2023     2   28
#> 10 2024     2   29
#> 11 2020     3   31
#> 12 2021     3   31
#> 13 2022     3   31
#> 14 2023     3   31
#> 15 2024     3   31
#> 16 2020     4   30
#> 17 2021     4   30
#> 18 2022     4   30
#> 19 2023     4   30
#> 20 2024     4   30