-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: The implied time zone of Date #203
Labels
breaking change ☠️
API change likely to affect existing code
Comments
Implementation: library(clock)
date_standardize <- function(x) {
if (identical(typeof(x), "double")) {
return(x)
}
# Convert somewhat rare integer Date to double.
# Preserves names.
storage.mode(x) <- "double"
x
}
date_cast <- function(x) {
UseMethod("date_cast")
}
date_cast.clock_time_point <- function(x) {
as.Date(x)
}
date_cast.clock_zoned_time <- function(x) {
# as.Date(x) if it worked with naive-time
as.Date(as_naive_time(x))
}
date_cast.clock_calendar <- function(x) {
as.Date(x)
}
# What as.Date.Date() should be
date_cast.Date <- function(x) {
date_standardize(x)
}
# What as.Date.POSIXct() and as.Date.POSIXlt() should be
date_cast.POSIXt <- function(x) {
date_cast(as_naive_time(x))
}
date_time_cast <- function(x, ...) {
UseMethod("date_time_cast")
}
date_time_cast.clock_sys_time <- function(x, zone, ...) {
ellipsis::check_dots_empty()
as.POSIXct(x, tz = zone)
}
date_time_cast.clock_naive_time <- function(x, zone, ..., nonexistent = NULL, ambiguous = NULL) {
ellipsis::check_dots_empty()
as.POSIXct(x, tz = zone, nonexistent = nonexistent, ambiguous = ambiguous)
}
date_time_cast.clock_zoned_time <- function(x, ...) {
ellipsis::check_dots_empty()
as.POSIXct(x)
}
date_time_cast.clock_calendar <- function(x, zone, ..., nonexistent = NULL, ambiguous = NULL) {
ellipsis::check_dots_empty()
as.POSIXct(x, tz = zone, nonexistent = nonexistent, ambiguous = ambiguous)
}
# What as.POSIXct.Date() should be
date_time_cast.Date <- function(x, zone, ..., nonexistent = NULL, ambiguous = NULL) {
date_time_cast(as_naive_time(x), zone, ..., nonexistent = nonexistent, ambiguous = ambiguous)
}
# What as.POSIXct.POSIXct() and as.POSIXct.POSIXlt() should be
date_time_cast.POSIXt <- function(x, ...) {
ellipsis::check_dots_empty()
x <- clock:::to_posixct(x)
x
}
date_today <- function(zone) {
# as.Date(zoned_time_now(zone)) if as.Date() works right
date_cast(zoned_time_now(zone))
}
date_time_now <- function(zone) {
as.POSIXct(zoned_time_now(zone))
} Examples: date_today("UTC")
#> [1] "2021-04-06"
date_today("America/New_York")
#> [1] "2021-04-06"
date_time_now("UTC")
#> [1] "2021-04-06 14:37:05 UTC"
date_time_now("America/New_York")
#> [1] "2021-04-06 10:37:05 EDT"
x <- as.POSIXct("2019-01-01 23:00:00", tz = "America/Los_Angeles")
date_cast(x)
#> [1] "2019-01-01"
x <- as.POSIXct("2019-01-01 23:00:00", tz = "UTC")
date_cast(x)
#> [1] "2019-01-01"
x <- as.Date("2019-01-01")
date_time_cast(x, "UTC")
#> [1] "2019-01-01 UTC"
date_time_cast(x, "America/New_York")
#> [1] "2019-01-01 EST"
# In Asia/Beirut, there was a DST gap from 23:59:59->01:00:00,
# skipping the 0 hour entirely
x <- as.Date("2021-03-28")
try(date_time_cast(x, "Asia/Beirut"))
#> Error : Nonexistent time due to daylight saving time at location 1. Resolve nonexistent time issues by specifying the `nonexistent` argument.
date_time_cast(x, "Asia/Beirut", nonexistent = "roll-forward")
#> [1] "2021-03-28 01:00:00 EEST"
# ^ same idea as
x <- as_naive_time(year_month_day(2021, 3, 28))
try(as_zoned_time(x, "Asia/Beirut"))
#> Error : Nonexistent time due to daylight saving time at location 1. Resolve nonexistent time issues by specifying the `nonexistent` argument. Path forward:
|
DavisVaughan
added
the
breaking change ☠️
API change likely to affect existing code
label
Apr 6, 2021
This was referenced Apr 7, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Currently, clock assumes that Date is UTC, because it seemed like this is also what base R assumed. I have now learned it is not quite that simple, and base R is actually inconsistent, treating Date as UTC or naive depending on the conversion being done
Sys.Date()
, Date is treated as naive-timeReferences:
?as.POSIXct.Date
states "Dates without times are treated as being at midnight UTC"?as.Date.POSIXct
"(POSIXct and POSIXlt are) converted to days by ignoring the time after midnight in the representation of the time in specified time zone, default UTC"?Sys.Date
states "Sys.Date returns the current day in the current time zone."This begs the question, what is most useful for clock? A few places this comes up:
as.Date.clock_zoned_time
andas_zoned_time.Date
date_today(zone = )
(Computed the current zoned-time, then convert to a Date, must assume naive or UTC) (Implementdate_now()
anddate_today()
#197)date_cast(x)
anddate_time_cast(x, zone, ..., nonexistent = , ambiguous =)
to be more consistent replacements foras.Date()
andas.POSIXct()
It seems like it may be more intuitive if Date was treated as naive-time at all times.
Created on 2021-04-06 by the reprex package (v1.0.0)
The text was updated successfully, but these errors were encountered: