I am trying to get the last minute of yesterday using Sys.Date()
in Posix time.
force_tz(as.POSIXlt(Sys.Date()-1), tz = 'America/New_York') + 86399
# [1] "2018-01-12 23:59:59 EST"
CORRECT
force_tz(as.POSIXct(Sys.Date()-1), tz = 'America/New_York') + 86399
# [1] "2018-01-12 15:59:59 EST"
INCORRECT
Sys.Date()
# [1] "2018-01-13"
Why does as.Posixct
and as.Posixlt
return two different values using Sys.Date()
and why is the difference 8 hours even after applying force_tz
from lubridate
?
As ever, debugonce
is your friend. Running debugonce(force_tz)
, you can see that the difference in output comes from when force_tz
hits the branches checking first is.POSIXct(time)
(in which case the default tzone = ""
is applied); in the POSIXlt
case, the default branch is hit, where as.POSIXct
is applied to time
and tz(time)
(which comes out as UTC
for a POSIXlt
object) is used as the time zone.
This comes down to something subtle happening; from ?as.POSIXlt.Date
:
Dates without times are treated as being at midnight UTC.
Hence
tz(as.POSIXlt(Sys.Date()-1))
# [1] "UTC"
But
tz(as.POSIXct(Sys.Date()-1))
# [1] ""
What's peculiar is this can't be overridden -- as.POSIXlt.Date
doesn't accept a tz
argument:
formals(as.POSIXlt.Date)
# $x
# $...
If you want to use POSIXct
, how about the following?
force_tz(as.POSIXct(sprintf('%s 00:00:00', Sys.Date())), 'America/New_York') - 1L
# [1] "2018-01-12 23:59:59 EST"