tidyverse / lubridate

Make working with dates in R just that little bit easier
https://lubridate.tidyverse.org
GNU General Public License v3.0
728 stars 207 forks source link

today() ignores provided time zone information #1111

Open zWarMob opened 1 year ago

zWarMob commented 1 year ago

Description

The function today does not return the correctly time-zoned date

Expected behavior

If I need a time-zoned date I expect lubridate to be able to pick up on my system time zone. Or at least when I provide it as an argument

with_tz(today(), Sys.timezone()) == today(Sys.timezone())
#> [1] TRUE

Actual behavior

I explicitly provide the time zone to the function today but it keeps reverting to UTC (can be seen if I do date math)

with_tz(today(), Sys.timezone()) == today(Sys.timezone())
#> [1] FALSE

Workaround

with_tz(today(), "GMT") gets me a date with the provided time zone.

Reprex

library(lubridate)
#> 
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#> 
#>     date, intersect, setdiff, union

Sys.timezone()
#> [1] "Europe/Paris"

today(Sys.timezone())
#> [1] "2023-03-22"

today(Sys.timezone()) - seconds(1)
#> [1] "2023-03-21 23:59:59 UTC"

today('UTC')
#> [1] "2023-03-22"

today('GMT')
#> [1] "2023-03-22"

# from https://lubridate.tidyverse.org/reference/now.html
# today() == today("GMT") # not always true
today() == today("GMT")
#> [1] TRUE

# Works as today("GMT") is supposed to?
with_tz(today(), "GMT")
#> [1] "2023-03-22 GMT"

Created on 2023-03-22 with reprex v2.0.2

zWarMob commented 1 year ago

I've fixed the problem for myself by forcing a time zone Pull request is here if this it the proper fix: https://github.com/tidyverse/lubridate/pull/1113/files

vspinu commented 1 year ago

Just to confirm, you want a Date object with time zone? Normally Date objects don't have a time zone. But given that we accept a tzone argument we should attach tzone attribute I think. This might be a regression.

Your PR produces POSIXct instead of Date BTW. The right approach is to attache a tzone attribute to the output.

> class(force_tz(today(), "GMT"))
[1] "POSIXct" "POSIXt" 
> class(today())
[1] "Date"
> 
zWarMob commented 1 year ago

Personally, I do want a time zone.

Disclaimer: I'm new to R and a noob so forgive me if I am wrong I see many methods are returning POSIXct. Except date(now()) and today()

Also there is some implicit conversion, because I subtract a Period from a Date and get POSIXct with a time zone. But no control over the time zone of the resulting POSIXct

today() - seconds(1)
zWarMob commented 1 year ago

If dates can have time zones,

else

moodymudskipper commented 1 year ago

The tz argument in today() is not meant to attach a timezone, a date has no timezone. The goal is to add a reference location to answer the question "what day is today" since the answer to this question is different in several places. At time of writing we have:

today("Europe/Paris")
#> [1] "2023-07-17"
today("Pacific/Auckland")
#> [1] "2023-07-18"

The documentation might be enhanced because it doesn't mention today() in the value field and the tzone arg description seems suited to now() rather than today().

On the other hand the function with_tz() will modify the timezone of a date time (POSIXct) object, keeping its value (point in time) intact. If we provide a date to this function it will transform it into a date time. The doc is quite clear in my opinion, though it might signal more clearly that dates are converted to midnight datetimes.

I believe a date with a time zone doesn't make much sense, better to use date times at midnight for this. So you might go with with_tz()

With your PR, today() returns a datetime instead of a date (the hours/minutes/seconds are just not printed).