Reputation: 1018
I have a situation where dates are written like this, with milliseconds:
2021/03/04 11:15:19.000
2021/03/04 11:15:19.999
I convert them to datetimes with lubridate and they look good and exactly the same:
> library(lubridate)
> as_datetime("2021/03/04 11:15:19.000")
[1] "2021-03-04 11:15:19 UTC"
> as_datetime("2021/03/04 11:15:19.999")
[1] "2021-03-04 11:15:19 UTC"
However, when I compare them they are not equivalent:
> as_datetime("2021/03/04 11:15:19.000") == as_datetime("2021/03/04 11:15:19.999")
[1] FALSE
But if simple dates, they are:
> as_date("2021/03/04 11:15:19.000") == as_date("2021/03/04 11:15:19.999")
[1] TRUE
Which creates problems for my workflow. It is particularly difficult to troubleshoot because there is no way to know that the milliseconds were different when simply looking at the processed dates because milliseconds don't show. Is there a way to have them read as equivalent datetimes?
My best workaround is to transform to character because they are equivalent in their character form:
> as.character(as_datetime("2021/03/04 11:15:19.000")) ==
as.character(as_datetime("2021/03/04 11:15:19.999"))
[1] TRUE
From this we can convert to datetimes again:
> as_datetime(as.character(as_datetime("2021/03/04 11:15:19.000"))) ==
as_datetime(as.character(as_datetime("2021/03/04 11:15:19.999")))
[1] TRUE
But this solution seems really convoluted. Surely there is a cleaner way to do this?
Upvotes: 2
Views: 831
Reputation: 368191
R stores datetime objects as a double
counting the fractional seconds since the epoch (i.e Jan 1, 1970). Note that we said fractional seconds. Your two observations were different when you read them, so R is quite correct in telling you that they are not equal.
But converting to Date
(which is a count of days rather than seconds since the epoch) you are doing a lossy conversion. A simpler way would have been trunc()
. As @akrun and @Dave2e hinted in the comments above, none of this has anything to do with lubridate
-- it is simply how R does business.
> d1 <- as.POSIXct("2021/03/04 11:15:19.000")
> d2 <- as.POSIXct("2021/03/04 11:15:19.999")
> d1 == d2
[1] FALSE
> trunc(d1) == trunc(d2)
[1] TRUE
>
Upvotes: 5