Skip to content
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

Implement date_now() and date_today() #197

Closed
AndrewKostandy opened this issue Apr 1, 2021 · 4 comments · Fixed by #210
Closed

Implement date_now() and date_today() #197

AndrewKostandy opened this issue Apr 1, 2021 · 4 comments · Fixed by #210
Labels
feature a feature request or enhancement

Comments

@AndrewKostandy
Copy link

I've looked for equivalent functions for lubridate's now() and today() functions that default to system time but also have a time zone argument but couldn't find any.

zoned_time_now() was the closest I could find to now(), but it doesn't have a precision argument to enable it to be equivalent. Not sure if I'm missing something. Thanks for the great package!

@DavisVaughan
Copy link
Member

zoned_time_now() is what you want. If you really want a Date or POSIXct, you can convert to them and that will convert precisions automatically. Otherwise if you want to stay with clock types then you convert to a time point, floor that, then convert back to a zoned-time (this is the general pattern with manipulating zoned-times).

library(lubridate)
library(clock)
library(magrittr)

l_now <- now("")
l_now
#> [1] "2021-04-01 12:09:59 EDT"

c_now <- zoned_time_now("")
c_now
#> <zoned_time<nanosecond><America/New_York (current)>[1]>
#> [1] "2021-04-01 12:09:59.678911000-04:00"

# if you want to get back to base R types (which changes precisions automatically)
as.POSIXct(c_now)
#> [1] "2021-04-01 12:09:59 EDT"

# you can do this, but be warned that it first converts from the `""` time zone
# to UTC, then floors to day precision and returns a Date. occasionally that
# will produce unexpected results depending on your local offset from UTC
as.Date(c_now)
#> [1] "2021-04-01"

# swap to a sys-time and back to adjust precision if you want to keep a zoned-time
c_now %>%
  as_sys_time() %>%
  time_point_floor("second") %>%
  as_zoned_time(zoned_time_zone(c_now))
#> <zoned_time<second><America/New_York (current)>[1]>
#> [1] "2021-04-01 12:09:59-04:00"

I could add date_now() and date_today() to the high level API if that seems useful? It would just be:

library(clock)

date_now <- function(zone = "") {
  as.POSIXct(zoned_time_now(zone))
}
date_today <- function(zone = "") {
  date_floor(date_now(zone), "day")
}

date_now()
#> [1] "2021-04-01 12:20:08 EDT"
date_today()
#> [1] "2021-04-01 EDT"

Note that date_today() would return a POSIXct in your requested time zone, not a Date (which is always assumed by base R to be UTC). This is different from lubridate::today(), but I think it is more appropriate, as with today() you can get into very odd scenarios like this one due to the fact that the way today() is computed sort of assumes that Date is time zone naive, which isn't the case.

library(lubridate)

# assume that now() returned this
now <- as.POSIXct("2019-01-01 23:00:00", "America/New_York")
now
#> [1] "2019-01-01 23:00:00 EST"

# today() calls `as_date(now())` like this.
# this glosses over the fact that we went from "America/New_York" -> "UTC",
# and sort of makes the assumption that Date is time zone naive, which isn't the case
today <- as_date(now)
today
#> [1] "2019-01-01"

# making this very confusing
as_datetime(today, "America/New_York")
#> [1] "2018-12-31 19:00:00 EST"

I probably would just expose date_now(), as date_today() is a bit redundant

@AndrewKostandy
Copy link
Author

Thanks for the detailed & clear response.

I think adding both might be worthwhile (I tend to use them frequently), but I find the name "date_now()" confusing as I wouldn't automatically realize it gives the time up to the second and not just the date as of now. date_today() would be great.

@DavisVaughan DavisVaughan changed the title Equivalents for now() and today() from lubridate with time zone argument Implement date_time_now() Apr 1, 2021
@DavisVaughan DavisVaughan added the feature a feature request or enhancement label Apr 1, 2021
@DavisVaughan DavisVaughan changed the title Implement date_time_now() Implement date_time_now() and maybe date_time_today() Apr 1, 2021
@DavisVaughan DavisVaughan changed the title Implement date_time_now() and maybe date_time_today() Implement date_now() and date_today() Apr 7, 2021
@DavisVaughan
Copy link
Member

@AndrewKostandy I've added these two in #210:

  • date_now() for the current date-time as a POSIXct
  • date_today() for the current date as a Date

While thinking about these, I learned that R does NOT always treat Date as UTC. Instead, it bounces between treating Date as UTC (i.e. sys-time in clock terms) and treating it as naive-time (i.e. a yet-to-be-specified time zone), depending on the function. You can see my full thoughts on this here #203

Since R is actually not consistent about this, I've ended up changing clock to consistently treat Date as a naive-time, rather than as UTC, as that seems to make more sense with how people use Dates. This had the side-effect of making date_today() well-defined and useful in my mind.

library(clock)

# system time zone
date_today("")
#> [1] "2021-04-07"

# current Date in Europe/London
date_today("Europe/London")
#> [1] "2021-04-07"

date_now("America/Los_Angeles")
#> [1] "2021-04-07 12:39:25 PDT"

Created on 2021-04-07 by the reprex package (v1.0.0)

@AndrewKostandy
Copy link
Author

AndrewKostandy commented Apr 7, 2021

Thanks for the update, Davis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants