From macrakis at alum.mit.edu  Sun Feb 22 22:51:49 2009
From: macrakis at alum.mit.edu (Stavros Macrakis)
Date: Sun, 22 Feb 2009 16:51:49 -0500
Subject: [Rd] Operations on difftime (abs, /, c)
In-Reply-To: <8b356f880902061517v66a364fenc2c0e7725ea6578c@mail.gmail.com>
References: <8b356f880902061517v66a364fenc2c0e7725ea6578c@mail.gmail.com>
Message-ID: <8b356f880902221351y7016e787pa8d27cdfdd57ad39@mail.gmail.com>

Forwarded from the r-help group -- r-devel seems more appropriate per
Duncan's recent email.

              -s

---------- Forwarded message ----------
From: Stavros Macrakis <macrakis at alum.mit.edu>
Date: Fri, Feb 6, 2009 at 6:17 PM
Subject: Operations on difftime (abs, /, c)
To: "r-help at r-project.org" <r-help at r-project.org>


Since both comparison and negation are well-defined for time
differences, I wonder why abs and division are not defined for class
difftime. This behavior is clearly documented on the man page:
"limited arithmetic is available on 'difftime' objects"; but why? Both
are natural, semantically sound, and useful operations and I see no
obvious reason that they should give an error:

     sec <- as.difftime(-3:3,units="secs")
     hour <- as.difftime(-3:3,units="hours")

     abs( sec ) => error  ... why not 3 2 1 0 1 2 3 secs?
     hour/sec => error   ... why not 3600, 3600, ... (dimensionless numbers)?

Of course, it is trivial to overload these operations for
difftime-class arguments:

     abs.difftime <- function(x) ifelse(x<0,-x,x)

    > abs(sec)
   [1] 3 2 1 0 1 2 3

   `/.difftime` <-
      function (e1, e2)
      {
       if (!inherits(e2, "difftime"))
     structure(unclass(e1)/e2, units = attr(e1, "units"), class = "difftime")
       else if (inherits(e1, "difftime"))
     as.numeric(e1,attr(e2, units = "units"))/as.numeric(e2)
       else
     stop("second argument of / cannot be a \"difftime\" object")    #
1/hour remains incorrect
      }

   > hour/sec
   [1] 3600 3600 3600  NaN 3600 3600 3600

Along the same lines, I don't understand why concatenation (c) should
strip the class of difftime, but not of POSIXt/ct:

    class( c(sec) ) => integer            <<< class and units
attribute are stripped
    class( c(sec,hour) ) => integer    <<< doesn't convert to common
unit, giving meaningless result
    class( c(Sys.time()) ) => "POSIXt" "POSIXct"

Again, c.difftime would be easy enough to define if it's the right thing to do.

So why wouldn't it be the right thing to do? Is there some semantic or
stylistic issue I'm missing here?

            -s



[Rd] Operations on difftime (abs, /, c)
Stavros Macrakis