discontinuity in evaluation of midnight POSIXct objects

╄→尐↘猪︶ㄣ 提交于 2019-12-24 08:24:54

问题


I have a vector of POSIXct objects with date and time, one of which is midnight.

v <- as.POSIXct(c("2019-01-01 23:59:00","2019-01-02 00:00:00"), tz="UTC")

When I evaluate v, it is shown correctly,

> v
[1] "2019-01-01 23:59:00 UTC" "2019-01-02 00:00:00 UTC"

but when I evaluate its elements separately,

> v[1]
[1] "2019-01-01 23:59:00 UTC"
> v[2]
[1] "2019-01-02 UTC"

the midnight element is shortened to exclude the time, which causes trouble in my data.table join. I therefore wonder whether it can be forced to be evaluated in full.

Found the answer!

> strftime(v, format="%Y-%m-%d %H:%M:%S")
[1] "2019-01-01 23:59:00" "2019-01-02 00:00:00" 
> strftime(v[1], format="%Y-%m-%d %H:%M:%S")
[1] "2019-01-01 23:59:00"
> strftime(v[2], format="%Y-%m-%d %H:%M:%S")
[1] "2019-01-02 00:00:00"

Setting time zone equal to system time zone is key.


回答1:


The good news: your data are still being represented correctly. It's only the print.POSIXct method that truncates it. (The offending code is actually inside format.POSIXlt, so it's only called for rendering the data onscreen.)

times <- as.POSIXct("2019-01-01 23:59:00") + c(0, 59, 60, 61)

times
[1] "2019-01-01 23:59:00 EST" "2019-01-01 23:59:59 EST" "2019-01-02 00:00:00 EST"
[4] "2019-01-02 00:00:01 EST"
as.list(times)
[[1]] [1] "2019-01-01 23:59:00 EST"

[[2]] [1] "2019-01-01 23:59:59 EST"

[[3]] [1] "2019-01-02 EST"

[[4]] [1] "2019-01-02 00:00:01 EST"
lapply(as.list(times), class)
[[1]]
[1] "POSIXct" "POSIXt" 

[[2]]
[1] "POSIXct" "POSIXt" 

[[3]]
[1] "POSIXct" "POSIXt" 

[[4]]
[1] "POSIXct" "POSIXt"
lapply(as.list(times), as.numeric)
[[1]]
[1] 1546405140

[[2]]
[1] 1546405199

[[3]]
[1] 1546405200

[[4]]
[1] 1546405201

The confusing news: if the times are coerced to character at any point in your join or processing, they won't print the same, but they will still point back to the same time when you re-coerce to a time. This is because as.POSIXct assumes the time of midnight if no HMS info is stored in the string.

lapply(as.list(times), as.character)
[[1]]
[1] "2019-01-01 23:59:00"

[[2]]
[1] "2019-01-01 23:59:59"

[[3]]
[1] "2019-01-02"

[[4]]
[1] "2019-01-02 00:00:01"
lapply(lapply(lapply(as.list(times), as.character), as.POSIXct), as.numeric)
[[1]]
[1] 1546405140

[[2]]
[1] 1546405199

[[3]]
[1] 1546405200

[[4]]
[1] 1546405201

The actions of igraph are outside my realm of expertise, but a good rule of thumb any time you have a complex data type that will be getting jostled around is to try to store it in an unambiguous string or number. Times are a great case for storing as integers, since they're (currently) represented under the hood as the number of seconds since the Unix origin of 1970-01-01.



来源:https://stackoverflow.com/questions/57084153/discontinuity-in-evaluation-of-midnight-posixct-objects

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!