R中字符串到日期的转换的“标准明确日期”格式是什么?


93

请考虑以下

$ R --vanilla

> as.Date("01 Jan 2000")
Error in charToDate(x) :
    character string is not in a standard unambiguous format

但该日期显然标准的明确格式。为什么会显示错误消息?

更糟糕的是,一个模棱两可的日期显然没有任何警告或错误就被接受,然后被错误地阅读!

> as.Date("01/01/2000")
[1] "0001-01-20"

我搜索并在[R]标记中找到包含此错误消息的28个其他问题。所有解决方案和解决方法都涉及指定iiuc格式。这个问题的不同之处在于,我要问的是,标准明确格式在哪里定义,并且可以更改吗?每个人都收到这些消息还是仅仅是我?也许与语言环境有关?

换句话说,是否有比指定格式更好的解决方案?

包含“ [R]标准明确格式”的29个问题

> sessionInfo()
R version 2.15.2 (2012-10-26)
Platform: x86_64-w64-mingw32/x64 (64-bit)

locale:
[1] LC_COLLATE=English_United Kingdom.1252
[2] LC_CTYPE=English_United Kingdom.1252
[3] LC_MONETARY=English_United Kingdom.1252
[4] LC_NUMERIC=C
[5] LC_TIME=English_United Kingdom.1252

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base

13
根据as.Date.character输入的功能定义判断,仅针对以下两种格式进行测试:"%Y-%m-%d""%Y/%m/%d"。如果它可以匹配其中之一,则似乎被认为是“明确的”。
plannapus

7
@CarlWitthoft“我什至读过”似乎暗示答案在中非常明显?as.Date。它在哪里有帮助?
马特·道尔

2
可以说“ 1949年1月24日”和“ 1949年1月24日”是明确的,但它们无疑是以英语为中心的。但是,也存在以英语为中心的'month.abb'值,因此在以下情况下可以使这些值匹配:strptime(xx, f <- "%d $B %Y", tz = "GMT")strptime(xx, f <- "%B $d %Y", tz = "GMT")返回值。(我并不是说这month.abb是用于%B的匹配,因为文档说匹配是特定于语言环境的。)
IRTFM

6
@CarlWitthoft我们中的一些人不时地绊倒。谢谢我摔倒时的踢踢。在这个问题中,我做了很多正确的事情:我包含了sessionInfo(),进行了搜索,告诉了我搜索的内容,并包含了链接,我尽可能地保持简洁。我错过了?as.Date的一行,而您给了我TFM治疗。我们不可能一直都像您一样完美。
马特·道尔

1
@MatthewDowle对不起,如果我认真下来。我认为,当您似乎将“对一个受过良好教育的人明确”与“对一个无能为力的无用代码段感到困惑”混为一谈。:-(
卡尔·威索夫特

Answers:


66

这是记录的行为。来自?as.Date

格式:字符串。如果未指定,它将在第一个非“ NA”元素上尝试先执行““%Y-%m-%d”“,然后尝试执行”“%Y /%m /%d”“,并且如果两者都不起作用,则给出错误。

as.Date("01 Jan 2000")产生错误,因为格式不是上面列出的两种格式之一。 as.Date("01/01/2000")产生错误的答案,因为日期不是上面列出的两种格式之一。

我用“标准明确”来表示“ ISO-8601”(尽管as.Date不是那么严格,因为“%m /%d /%Y”不是ISO-8601)。

如果收到此错误,解决方案是使用中描述的格式指定日期(或日期时间)所用的格式?strptime。确保使用特别小心,如果你的数据包含日/月的名称和/或缩写,作为转换将取决于您的区域设置(见实例?strptime和读取?LC_TIME)。


6
@BenBolker怎么样"character string is not either %Y-%m-%d or %Y/%m/%d"
Matt Dowle

9
该行为肯定记录在?as.Date(+1)中。但是,错误消息“标准明确格式”是具有讽刺意味的模棱两可,先前的23个问题证明了这一点。更直接的错误消息,例如“无法识别格式,请参阅文档”可能会改善用户体验。另外,我不认为“ 01/01/2000”是ISO-8601(“ 2000-01-01”是ISO-8601),这增加了歧义。
jthetzel

@jthetzel:是的,“ 01/01/2000”不是ISO-8601。我的意思是我个人认为ISO-8601是标准,明确的格式。而且我同意as.Date不抱怨“ 01/01/2000”与错误消息不一致。
2015年

31

换句话说,是否有比指定格式更好的解决方案?

是的,现在(即在2016年后期),这要归功于anytime::anydate随时随地包。

请参阅以下内容,以获取上述示例:

R> anydate(c("01 Jan 2000", "01/01/2000", "2015/10/10"))
[1] "2000-01-01" "2000-01-01" "2015-10-10"
R> 

正如您所说,这些实际上是明确的,应该可以正常工作。通过anydate()他们做。没有格式。


2
之所以来到这里,是因为我们还有另一个问题,试图解析格式不完整的日期。对于完整的,我们现在有一些东西。我对此感到非常满意-这是一个令人讨厌的问题。不用说,anytime()对于同样有用POSIXct
Dirk Eddelbuettel,2016年

只是使用了anytime程序包,除了很多NA之外,它的运行都非常出色。在日期向量上运行trimws()之后,一切都变得很完美。
lawyeR

我也用公吨!
Dirk Eddelbuettel

看起来好简单!我在字符串值为mm-dd(否yy)的列上使用了anydate()。列中的所有<chr>值都已成功转换为<date>。不幸的是,它将年份设置为“ 1400”,而不是“ 2020”。_(ツ)_ /¯
owlstone

好吧,不完全是。正如我在此网站上的其他几个问题中回答的那样,mm-dd它不是日期(mm-yy或mm-yyyy都不是)。您无法解析不存在的内容。
Dirk Eddelbuettel

26

作为@JoshuaUlrich答案的补充,这是function的定义as.Date.character

as.Date.character
function (x, format = "", ...) 
{
    charToDate <- function(x) {
        xx <- x[1L]
        if (is.na(xx)) {
            j <- 1L
            while (is.na(xx) && (j <- j + 1L) <= length(x)) xx <- x[j]
            if (is.na(xx)) 
                f <- "%Y-%m-%d"
        }
        if (is.na(xx) || !is.na(strptime(xx, f <- "%Y-%m-%d", 
            tz = "GMT")) || !is.na(strptime(xx, f <- "%Y/%m/%d", 
            tz = "GMT"))) 
            return(strptime(x, f))
        stop("character string is not in a standard unambiguous format")
    }
    res <- if (missing(format)) 
        charToDate(x)
    else strptime(x, format, tz = "GMT")
    as.Date(res)
}
<bytecode: 0x265b0ec>
<environment: namespace:base>

所以基本上如果同时strptime(x, format="%Y-%m-%d")strptime(x, format="%Y/%m/%d")抛出NA它被认为是不明确的,如果没有明确。


6

在不指定当前格式的情况下转换日期会很容易给您带来此错误。

这是一个例子:

sdate <- "2015.10.10"

在不指定格式的情况下进行转换:

date <- as.Date(sdate4) # ==> This will generate the same error"""Error in charToDate(x): character string is not in a standard unambiguous format""".

以指定格式转换:

date <- as.Date(sdate4, format = "%Y.%m.%d") # ==> Error Free Date Conversion.

2

不管日期是如何编码的,这对我来说都是完美的。

library(lubridate)
data$created_date1 <- mdy_hm(data$created_at)
data$created_date1 <- as.Date(data$created_date1)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.