lubridate icon indicating copy to clipboard operation
lubridate copied to clipboard

update and make_datetime handling of Februray 29

Open Blundys opened this issue 6 years ago • 3 comments
trafficstars

Hi I have found a bug in update, the roll argument does not seem to be doing anything. Even when set to FALSE it is returning the next valid point instead of NA for non existing date-times.

Similarly make_datetime rolls to the next date by default, with no option to change this which would be desirable.

library(lubridate)

LeapYearDate <- as.POSIXct("2016-02-29, 02:00", tz = "UTC")

update(LeapYearDate, years = 2015,roll = FALSE)
#> [1] "2015-03-01 UTC"
update(LeapYearDate, years = 2015,roll = TRUE)
#> [1] "2015-03-01 UTC"

make_datetime(year = 2015, month = 2, day = 29)
#> [1] "2015-03-01 UTC"

Created on 2019-05-28 by the reprex package (v0.3.0)

Blundys avatar May 28 '19 04:05 Blundys

So looking at this for the TDD there are two issues here, the first is that roll doesn't seem to be returning NA when false. The second, as far as I can tell looking at the make_datetime code is doesn't appear to have any checks to see if the date is a valid date?

Maschette avatar Jul 08 '19 08:07 Maschette

Looks like another issue fixed by timechange:

library(lubridate, warn.conflicts = FALSE)
x <- as.POSIXct("2016-02-29, 02:00", tz = "UTC")

update(x, years = 2015)
#> [1] "2015-03-01 UTC"
update(x, years = 2015, roll = FALSE)
#> [1] "2015-03-01 UTC"

timechange::time_update(x, year = 2015)
#> [1] "2015-03-01 UTC"
timechange::time_update(x, year = 2015, roll_month = "NA")
#> [1] NA

Created on 2019-11-19 by the reprex package (v0.3.0)

hadley avatar Nov 19 '19 23:11 hadley

This is an error by default in clock, which provides multiple ways to resolve the invalid date:

library(clock)

x <- as.POSIXct("2016-02-29, 02:00", tz = "UTC")

# Error by default
set_year(x, 2015)
#> Error: Invalid date found at location 1.
#> ℹ Resolve invalid date issues by specifying the `invalid` argument.

# If you want to throw this out
set_year(x, 2015, invalid = "NA")
#> [1] NA

# Next moment in time
set_year(x, 2015, invalid = "next")
#> [1] "2015-03-01 UTC"

# Previous moment in time
set_year(x, 2015, invalid = "previous")
#> [1] "2015-02-28 23:59:59 UTC"

Created on 2021-05-25 by the reprex package (v1.0.0)

DavisVaughan avatar May 25 '21 13:05 DavisVaughan

roll argument wasn't affecting rolling behavior of month days. It was controling only the DST skipped behavior. There are new arguments in lubridate roll_month and roll_dst which allow for full control of rolling and updating.

> leap <- ymd_hms("2016-02-29 02:00:00", tz = "UTC")
> update(leap, years = 2015, roll_month = "postday")
[1] "2015-03-01 02:00:00 UTC"
> update(leap, years = 2015, roll_month = "preday")
[1] "2015-02-28 02:00:00 UTC"
> update(leap, years = 2015, roll_month = "boundary")
[1] "2015-03-01 UTC"

vspinu avatar Nov 02 '22 21:11 vspinu