6

I recently came across R code that compared a POSIXlt date object with a date string.

as.POSIXlt.date("2007-02-02") >= "2007-02-01"
[1] FALSE

The result, surprisingly at least for me, was FALSE. I was expecting that the POSIXlt object would be coerced in to a character vector and so the inequality should test TRUE. I then tried explicit coercion and coercing either side in to the other's type yielded true.

as.character(as.POSIXlt.date("2007-02-02")) >= "2007-02-01"
[1] TRUE

and

as.POSIXlt.date("2007-02-02") >= as.POSIXlt.date("2007-02-01")
[1] TRUE

I think coercing the LHS date object to a character vector is semantically wrong because the comparison then would be lexicographic which is not what is intended (although it evaluates to TRUE in this case). Am I right?

In my opinion third expression is semantically right code. But why does the first code not work (it evaluates to FALSE)? Doesn't R coerce both sides to character vectors before comparing them?

Here's my platform information:

R version 3.1.0 (2014-04-10) -- "Spring Dance"
Platform: x86_64-redhat-linux-gnu (64-bit)

I am new to R. Any help is much appreciated.

Thanks, Farhan

vrajs5
  • 4,066
  • 1
  • 27
  • 44
farhanhubble
  • 476
  • 3
  • 18
  • I thought I understood why but after looking at the code I'm now confused. It appears both arguments should be coerced to POSIXct but are not. Thought `Ops.POSIXt` would be called but now thinking that since the comparison operators are Primitive that no class checking is done. – IRTFM Sep 08 '14 at 20:19
  • What version of R are you running? When I copy/paste `as.POSIXlt.date("2007-02-02") >= "2007-02-01"` into my R session i get `TRUE` (verision 3.1.1). @BondedDust at least for me, if I do `debugonce(Ops.POSIXt)` I can see that function is being called. OP, does `as.POSIXlt.date("2007-02-02") == as.POSIXct("2007-02-02")` return `TRUE` for you? What is your `Sys.timezone()`? – MrFlick Sep 08 '14 at 21:23
  • I'm still using R 3.1.0 (Patched). I looked through the NEWS file and do not see where this was specifically reported as a bug or a fix. I was using trace() and did not see that `Ops.POSIXt` was called, but do see it appear with `debugonce`. Now I'm wondering if the second instance I see of `as.character(e1)` in the conditional before the operation on 'e2' was changed to `as.character(e2)` but not recorded in the NEWS file. – IRTFM Sep 08 '14 at 21:32
  • 2
    So the answer seems to be that ... no, the comparison is not done as a character, but as a numeric.... after both are coerced with as.POSIXct ... but only in the most up-to-date version of R. I can confirm that updating to 3.1.1 gives the expected answer: `> as.POSIXlt.date("2007-02-02") >= "2007-02-01" # [1] TRUE` – IRTFM Sep 08 '14 at 21:40
  • Thanks @BondedDust I'm using R 3.1.0. Is there any documentation on such conversion to POSIXct? I have not been able to find much information on coercion in general except for the precious few lines in the help pages. I quote them here. "If the two arguments are atomic vectors of different types, one is coerced to the type of the other, the (decreasing) order of precedence being character, complex, numeric, ..." and "At least one of ‘x’ and ‘y’ must be an atomic vector, but if the other is a list R attempts to coerce it to the type of the atomic vector". – farhanhubble Sep 09 '14 at 01:37
  • You did expect some sort of coercion and R does quite a bit of implicit coercion. There is some material as `?as` and more material at `?mode` if you are looking for material on general issues of coercion of R objects. I did not find much that was specific to `POSIXt` objects, so needed to go to the code, which in my case (and yours) was misleading. That doesn't usually happen to me. Usually going to the code clarifies things for me, unless it is in C-calls. – IRTFM Sep 09 '14 at 01:54

1 Answers1

1

In general, dates should all be of class Date when doing comparisons.

It works in some cases because R converts the String "2007-02-01" into a Date behind the scenes, which can fail in some cases:

as.Date("2020-09-12") <= "2020:09:13"
# Error in charToDate(x) : 
#   character string is not in a standard unambiguous format

Also, be aware of the different Date methods, which are incompatible:

as.POSIXlt("2007-02-02") <= as.Date("2020,01,12", "%Y,%m,%d")
#   sec    min   hour   mday    mon   year   wday   yday  isdst   zone gmtoff 
#  TRUE   TRUE   TRUE   TRUE   TRUE   TRUE   TRUE   TRUE   TRUE     NA     NA 
#Warning messages:
#1: Incompatible methods ("Ops.POSIXt", "Ops.Date") for "<=" 
#2: NAs introduced by coercion 

Btw, I can't reproduce the first example anymore (R version 4.0.3):

as.POSIXlt.date("2007-02-02") >= "2007-02-01"
# Error in as.POSIXlt.date("2007-02-02") : 
#   could not find function "as.POSIXlt.date"

as.POSIXlt.Date("2007-02-02") >= "2007-02-01"
# [1] NA
# Warning message:
# In as.POSIXlt.Date("2007-02-02") : NAs introduced by coercion
Andre Wildberg
  • 12,344
  • 3
  • 12
  • 29