两个紧密时间字符串的奇怪 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"
三个问题:
- 为什么两条线的时区不同
- 为什么没有给出格式时它会忽略时间部分。
- 为什么指定格式后第一个字符串转换失败?
- Why the time zone differs between the two lines
如评论中所述,由于夏令时而有所不同。由于您不在对 as.POSIXct
的调用中包括该区域,因此您很容易遇到很多问题。尽可能明确时区。这不是开玩笑的时刻:如果您知道它(并且它不是字符串的一部分),永远不会 假定它会被正确推断。根据我的经验,它会出错,非常烦人,而且很难检测、查找和修复。
- 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"
- 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 区域
- 可能还有其他我没有根除的东西
我不完全理解将数据和时间字符串转换为 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"
三个问题:
- 为什么两条线的时区不同
- 为什么没有给出格式时它会忽略时间部分。
- 为什么指定格式后第一个字符串转换失败?
- Why the time zone differs between the two lines
如评论中所述,由于夏令时而有所不同。由于您不在对 as.POSIXct
的调用中包括该区域,因此您很容易遇到很多问题。尽可能明确时区。这不是开玩笑的时刻:如果您知道它(并且它不是字符串的一部分),永远不会 假定它会被正确推断。根据我的经验,它会出错,非常烦人,而且很难检测、查找和修复。
- 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"
- 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 区域
- 可能还有其他我没有根除的东西