Home > other >  Why round_date() returns error for some units?
Why round_date() returns error for some units?

Time:03-03

I try to round dates (POSIXlt object) to the nearest 5 minutes. I tried to use round_date() function and run into following situation:

> date
[1] "2012-11-01 15:41:00 EET"
> is.POSIXlt(date)
[1] TRUE
> round_date(date, "hour")
[1] "2012-11-01 16:00:00 EET"
> round_date(date, "min")
[1] "2012-11-01 15:41:00 EET"
> round_date(date, "5 mins")
Error in above - mid : non-numeric argument to binary operator

It seems to work for second, minute, hour and day. All the other units listed in the examples return this error.

I followed the advice from this thread and specified tz, but this didn't change anything.

period() function seems to work fine:

> period("5 mins")
[1] "5M 0S"

The above example is for the sake of simplicity as this data is a part of data frame. I don't know if that is relevant, but I also tried to work around it using mutate and replace. That failed with

x 'origin' must be supplied

Thanks!

EDIT

The problem was reproducible for POSIXlt objects. Bug report is submitted. Quick fix for my problem was:

> round_date(as.POSIXct(date), "5 mins")
[1] "2012-11-01 15:40:00 EET"

CodePudding user response:

Placing a numeric modifier prior to one of the supported time units is not a supported option for the round.POSIXt function/method, at least it's not documented in the help page. Such a feature is supported for seq.POSIXt and cut.POSIXt, so I can certainly see why that might have been a reasonable assumption. You could get that as a desired result by doing modulo division by the seconds equivalent of 5 mins and then ordinary multiplication by that amount, but you would of course need to reconvert to POSIXlt class. One of the gotcha's of as.POSIXt.numeric is that you do need to specify an "origin" which is typically "1970-01-01". (Seems to me that it ought to be a default assumption.)

Allan is correct in thinking that yet again I've been too hasty im my reading of a question. (It might have helped if I had seen something along the lines of:

library(lubridate)

[EDIT] My new guess is that this is something to do with Daylight-to-Standard Time switchover. I'm unable to replicate the error with:

x <- lubridate::ymd_hms("2009-08-03 12:01:59.23")
lubridate::round_date(x, "5 mins")
[1] "2009-08-03 12:00:00 UTC"

The EET DST-> Standard transition is

Eastern European Time (EET), observed in countries including Bulgaria, Estonia, Finland, Greece, Latvia, Romania, Turkey, Ukraine. Daylight saving time starts at 03:00 local time, when clocks move forward to 04:00.

The Daylight Saving Time (DST) period in Europe runs from 01:00 UTC (Coordinated Universal Time) on the last Sunday of March to 01:00 UTC on the last Sunday of October every year.

[Further EDIT]; Wrong again. And now I am able to cause the undesirable action. Advancing the hour beyond the 3-4 hour does not cure the problem when a "ymd_hms"-created vector is converted to POSIXlt class:

 x <- lubridate::ymd_hms("2012-11-01 15:41:00 EET",tz="EET")
 lubridate::round_date(x, "5 mins")
#[1] "2012-11-01 15:40:00 EET"

x <- lubridate::ymd_hms("2012-11-01 17:41:00 EET",tz="EET")
 lubridate::round_date(as.POSIXlt(x), "5 mins")
#Error in above - mid : non-numeric argument to binary operator

Could there be a bug in pkg:lubridate when operating on POSIXlt objects? There's no error operating on POSIXct objects:

lubridate::round_date(as.POSIXct(x), "5 mins")
[1] "2012-11-01 17:40:00 EET"

The way to report suspected bugs in R package is to run:

maintainer("lubridate")
#[1] "Vitalie Spinu <[email protected]>"

And send a report with a [MCVE].

  • Related