1

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.

bumblebee
  • 1,116
  • 8
  • 20
  • could you show me the two `data.tables` you want to join, and with what command you want to do that? – TobiO Jul 17 '19 at 21:19
  • The whole join includes a graph and it generally described [here](https://stackoverflow.com/questions/56983943/igraph-posixct), except that I also use `as.character(timeA) %chin% names(subcomponent(g, as.character(timeB)))`. Coming to think of it, it is probably the `subcomponent(.)` command of `igraph` where the problem originates. – bumblebee Jul 17 '19 at 21:22

1 Answers1

0

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.

Brian
  • 7,900
  • 1
  • 27
  • 41