Perhaps this is intentional, but it strikes me as unexpected:
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following object is masked from 'package:base':
#>
#> date
tz(today())
#> [1] "UTC"
tz(force_tz(today(), "America/New_York"))
#> [1] "UTC"
tz(with_tz(today(), "America/New_York"))
#> [1] "America/New_York"
Latest Github version, 1.7.4.
In general, timezones for pure Date
s seem to be discouraged in that virtually no lubridate functions will ever return a non-UTC date (e.g. today
, as_date
, date
, etc.), but I can't find anything to this effect in the docs.
I think the last two should return POSIX instead of date. I would qualify this as a bug.
Do you also find the first example unexpected? This is a new addition in the last minor version to avoid dealing explicitly with the NULL tzs, but I am not entirely convinced it was such a good idea.
I strongly recommend against up-converting dates to datetime in general, and I think doing so implicitly would be asking for trouble. The typical approach there is to assume the time is all-zeroes, but then with_tz
can easily change the date which I suspect is rarely the desired outcome.
I hadn't thought of it when I created this issue, but on reflection, yes I think the first result is unexpected, given that I have a non-UTC locale set.
Would it make sense to drop timezones from time-free Date
s altogether? e.g. tz
would error or return NULL
, with_tz
/force_tz
could warn or error, etc.
Potential problems might include edge cases like Samoa's missing day (https://zachholman.com/talk/utc-is-enough-for-everyone-right).
You ask for an operation which makes sense on date-times, that implise that you are interpreting the date as an instant. Otherwise why would you do force_tz on a date?
Would it make sense to drop timezones from time-free Dates altogether?
Yes. I will revert it to NULL.
I agree force_tz
doesn't make sense; I only tried it because I didn't get the expected behavior from with_tz
. For consistency across a mix of dates and datetimes, my goal was to _set_ the correct timezone, and tz(x) <- "America/New_York"
leads to awkward code. After this discussion I don't even want to do that; I think we're in agreence that dates should not have timezones in any manner.
I'm happy to help with code, though I won't have time until at least tomorrow. Sounds like you want tz
to return NULL
; what about force_tz
/with_tz
? Erroring would make it clear lubridate
doesn't support timezones on dates, but might also break users code. Could throw a warning in one release and an error in a subsequent release if breakage is a concern, but it's possible nobody else is trying to set timezones on their dates like I did.
It seems reasonable to me to return POSIXct when you explicit request a timezone be added to a Date. Adding a tzone attribute to a Date object is definitely wrong:
library(lubridate, warn.conflicts = FALSE)
tz(force_tz(today(), "America/New_York"))
#> [1] "UTC"
class(force_tz(today(), "America/New_York"))
#> [1] "Date"
tz(with_tz(today(), "America/New_York"))
#> [1] "America/New_York"
class(with_tz(today(), "America/New_York"))
#> [1] "Date"
tz(`tz<-`(today(), "America/New_York"))
#> [1] "UTC"
class(`tz<-`(today(), "America/New_York"))
#> [1] "Date"
Created on 2019-11-20 by the reprex package (v0.3.0)
(I agree that lubridate seems to upclass dates to date-times too readily; but that's a separate issue)