为什么 chron 包从 2030 年开始奇怪地对待两位数的年份?
Why is the chron package treating 2 digit years oddly starting from 2030?
我最近注意到 R 中有一个我无法解释的奇怪行为。我在一些旧代码中有这个:
以下应生成从 01/1980 -> 01/2029 的月份列表,并且按预期工作:
length(chron::seq.dates("01/31/80", "01/03/29", by="months"))
[1] 588
这就是事情变得奇怪的地方。以下内容与上述内容相同,但应生成 2030 年之前的日期:
length(chron::seq.dates("01/31/80", "01/03/30", by="months"))
Error during wrapup: "from" must be a date before "to"
那么这里发生了什么?
最好转换为 Date
class,因为当我们延长年份时,两位数的年份可能是个问题。
library(chron)
date1 <- as.Date("01/31/80", format = "%m/%d/%y")
date2 <- as.Date("01/03/30", format = "%m/%d/%y")
这里,转换正确
date1
#[1] "1980-01-31"
date2
#[1] "2030-01-03"
基于 ?seq.dates
,我们可以传递 character
字符串或 numeric
值(将 'Date' class 转换为 'numeric'
length(seq.dates(as.numeric(date1), as.numeric(date2), by = "months"))
#[1] 600
或julian
日期
j1 <- julian(date1, origin = as.Date('1970-01-01'))
j2 <- julian(date2, origin = as.Date('1970-01-01'))
length(seq.dates(j1, j2, by = 'months'))
#[1] 600
或使用 character
格式的 4 位数年份
length(chron::seq.dates("01/31/1980", "01/03/2030", by="months"))
#[1] 600
如果日期已经有 2 位数字,可以用 sub
插入特定数字
sub("(\d+)$", "20\1", "01/03/30")
#[1] "01/03/2030"
并在 seq.dates
中传递该值
length(seq.dates("01/31/80", sub("(\d+)$", "20\1", "01/03/30"), by = "months"))
#[1] 600
当将两位数年份扩展为四位数年份时,默认情况下 chron 截止值为 30。也就是说,如果两位数年份小于 30,则假定为 20yy,否则为 19yy。这是由 chron.year.expand
选项控制的,该选项默认设置为 chron year.expand
函数,该函数又具有默认截止值 30,但可以按如下方式更改:
library(chron)
# change cutoff to 50
options(chron.year.expand =
function (y, cut.off = 50, century = c(1900, 2000), ...) {
chron:::year.expand(y, cut.off = cut.off, century = century, ...)
}
)
length(seq.dates("01/31/80", "01/03/30", by="months"))
## [1] 600
这些中的每一个都可以工作,并且不需要设置 chron.year.expand
:
length(seq(as.chron("1980-01-31"), as.chron("2030-01-03"), by="months"))
length(seq.dates("01/31/80", as.chron("2030-01-03"), by="months"))
length(seq.dates("01/31/80", chron(julian(1, 3, 2030)), by="months"))
length(seq.dates("01/31/80", julian(1, 3, 2030), by="months"))
length(as.chron(seq(as.Date("1980-01-31"), as.Date("2030-01-03"), by = "month")))
length(seq.dates("01/31/80", length = 600, by="months"))
在 Linux Mint 上使用 R4.1 运行ning,下面的代码显示了我所看到的。默认截止值似乎是 68,而不是 30。有没有办法在给定的 R 安装中将真正的默认截止值指定为 30?换句话说,我不想每次 运行 R.
时都必须 运行 上面给出的选项函数将其设置为 30
library(chron)
chron("2/29/68")-chron("11/23/69")
Time in days:
[1] 35892
chron("2/29/1968")-chron("11/23/1969")
[1] -633
options(chron.year.expand =
-
function (y, cut.off = 30, century = c(1900, 2000), ...) {
-
chron:::year.expand(y, cut.off = cut.off, century = century, ...)
-
}
- )
chron("2/29/68")-chron("11/23/69")
[1] -633
chron("2/29/1968")-chron("11/23/1969")
[1] -633
我最近注意到 R 中有一个我无法解释的奇怪行为。我在一些旧代码中有这个:
以下应生成从 01/1980 -> 01/2029 的月份列表,并且按预期工作:
length(chron::seq.dates("01/31/80", "01/03/29", by="months"))
[1] 588
这就是事情变得奇怪的地方。以下内容与上述内容相同,但应生成 2030 年之前的日期:
length(chron::seq.dates("01/31/80", "01/03/30", by="months"))
Error during wrapup: "from" must be a date before "to"
那么这里发生了什么?
最好转换为 Date
class,因为当我们延长年份时,两位数的年份可能是个问题。
library(chron)
date1 <- as.Date("01/31/80", format = "%m/%d/%y")
date2 <- as.Date("01/03/30", format = "%m/%d/%y")
这里,转换正确
date1
#[1] "1980-01-31"
date2
#[1] "2030-01-03"
基于 ?seq.dates
,我们可以传递 character
字符串或 numeric
值(将 'Date' class 转换为 'numeric'
length(seq.dates(as.numeric(date1), as.numeric(date2), by = "months"))
#[1] 600
或julian
日期
j1 <- julian(date1, origin = as.Date('1970-01-01'))
j2 <- julian(date2, origin = as.Date('1970-01-01'))
length(seq.dates(j1, j2, by = 'months'))
#[1] 600
或使用 character
格式的 4 位数年份
length(chron::seq.dates("01/31/1980", "01/03/2030", by="months"))
#[1] 600
如果日期已经有 2 位数字,可以用 sub
sub("(\d+)$", "20\1", "01/03/30")
#[1] "01/03/2030"
并在 seq.dates
length(seq.dates("01/31/80", sub("(\d+)$", "20\1", "01/03/30"), by = "months"))
#[1] 600
当将两位数年份扩展为四位数年份时,默认情况下 chron 截止值为 30。也就是说,如果两位数年份小于 30,则假定为 20yy,否则为 19yy。这是由 chron.year.expand
选项控制的,该选项默认设置为 chron year.expand
函数,该函数又具有默认截止值 30,但可以按如下方式更改:
library(chron)
# change cutoff to 50
options(chron.year.expand =
function (y, cut.off = 50, century = c(1900, 2000), ...) {
chron:::year.expand(y, cut.off = cut.off, century = century, ...)
}
)
length(seq.dates("01/31/80", "01/03/30", by="months"))
## [1] 600
这些中的每一个都可以工作,并且不需要设置 chron.year.expand
:
length(seq(as.chron("1980-01-31"), as.chron("2030-01-03"), by="months"))
length(seq.dates("01/31/80", as.chron("2030-01-03"), by="months"))
length(seq.dates("01/31/80", chron(julian(1, 3, 2030)), by="months"))
length(seq.dates("01/31/80", julian(1, 3, 2030), by="months"))
length(as.chron(seq(as.Date("1980-01-31"), as.Date("2030-01-03"), by = "month")))
length(seq.dates("01/31/80", length = 600, by="months"))
在 Linux Mint 上使用 R4.1 运行ning,下面的代码显示了我所看到的。默认截止值似乎是 68,而不是 30。有没有办法在给定的 R 安装中将真正的默认截止值指定为 30?换句话说,我不想每次 运行 R.
时都必须 运行 上面给出的选项函数将其设置为 30library(chron)
chron("2/29/68")-chron("11/23/69") Time in days: [1] 35892
chron("2/29/1968")-chron("11/23/1969") [1] -633
options(chron.year.expand =
-
function (y, cut.off = 30, century = c(1900, 2000), ...) {
-
chron:::year.expand(y, cut.off = cut.off, century = century, ...)
-
}
- )
chron("2/29/68")-chron("11/23/69") [1] -633
chron("2/29/1968")-chron("11/23/1969") [1] -633