两个紧密时间字符串的奇怪 POSIX 行为,有和没有指定格式

Weird POSIX behaviour for two closely time strings with and without specifying the format

我不完全理解将数据和时间字符串转换为 POSIX 对象的行为。例如,我有一个由表示日期和时间的两个字符串组成的向量。指定格式的转换 w/o 忽略时间部分,并将时区设置为 IST:

as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'))
[1] "2017-03-24 IST" "2017-03-24 IST"

但是当我指定格式时,它设置为不同的时区,并且对于小时为“2”的字符串失败,但如果时间是第二个则不会。

as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), format="%Y-%m-%d %H:%M:%OS")
[1] NA "2017-03-24 03:00:00 IDT"

三个问题:

  1. 为什么两条线的时区不同
  2. 为什么没有给出格式时它会忽略时间部分。
  3. 为什么指定格式后第一个字符串转换失败?
  1. Why the time zone differs between the two lines

如评论中所述,由于夏令时而有所不同。由于您不在对 as.POSIXct 的调用中包括该区域,因此您很容易遇到很多问题。尽可能明确时区。这不是开玩笑的时刻:如果您知道它(并且它不是字符串的一部分),永远不会 假定它会被正确推断。根据我的经验,它会出错,非常烦人,而且很难检测、查找和修复。


  1. Why when no format is given it ignores the times' portion

它不是,尽管它可能看起来像。这只是 打印 而非存储方式的一个症状。 (这在 R 的许多函数中很常见,例如它如何显示 pi 只有少数小数位,但肯定会存储更多。如果没有这个 "representation versus actual precision" 模型,R 的控制台将不必要地充满一直都是小数位等等。)

如果我更新您的代码以明确包含区域:

as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel")
# [1] "2017-03-24 IST" "2017-03-24 IST"
as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel") + 1
# [1] "2017-03-24 00:00:01 IST" "2017-03-24 00:00:01 IST"

第二种情况,我把时间加了一秒,你看现在时间到了。您可以查看内部结构以不同的方式查看它:

dput(as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel"))
# structure(c(1490306400, 1490306400), class = c("POSIXct", "POSIXt"
# ), tzone = "Israel")
dput(as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel")+1)
# structure(c(1490306401, 1490306401), tzone = "Israel", class = c("POSIXct", 
# "POSIXt"))

时间存储为浮点数和一个特殊的 class。在两者之间(没有和有 1 秒相加),您可以看到数字只是相差一个。

第三种确认方法是获取 "missing time" posix 对象并显式打印到某些东西(不再是 POSIXct,但它只是为了演示):

a <- as.POSIXct(c('2017-03-24 02:59:59', '2017-03-24 03:00:00'), tz="Israel")
a
# [1] "2017-03-24 IST" "2017-03-24 IST"
format(a, format="the time is %Y-%m-%d %H:%M:%S")
# [1] "the time is 2017-03-24 00:00:00" "the time is 2017-03-24 00:00:00"

  1. Why does it fail to convert the first string when the format is specified?

正如@Dave2e 评论的那样,根据夏令时转换,那个时间 "never happened"。

根据https://www.timeanddate.com/time/change/israel/jerusalem?year=2017

Mar 24, 2017 - Daylight Saving Time Started

When local standard time was about to reach Friday, March 24, 2017, 2:00:00 am clocks were turned forward 1 hour to Friday, March 24, 2017, 3:00:00 am local daylight time instead.

我认为这意味着时钟从 01:59:59 转移到 03:00:00,所以 02:**:** 从未发生过。 R 用 NA 告诉你那个时间不应该发生。肯定有一些方法(hacks)可以推断是这种情况:找到所有NA值,然后尝试使用正负一小时重新转换;如果新值不是 NA,那么你发现了另一个 R 认为时间不可能的实例。如果它仍然是 NA,那么这个字符串一定有其他的东西(额外的字符、不同的顺序等)。

根据我的经验,我从未发现此逻辑有误(尽管我不确定它是否完美无缺),即使它看起来很烦人。当我认为它可能不正确时,我总能找到其他东西来解释为什么我认为我有 那个精确时间:

  • 数据采集存储了错误的TZ
  • 数据采集存储TZ失败,我推断错误
  • 管道中的某些转换错误转换了时间 and/or 区域
  • 可能还有其他我没有根除的东西