DavisVaughan / datea

Extended Date Classes
Other
1 stars 0 forks source link

Differences with other implementations #8

Open DavisVaughan opened 4 years ago

DavisVaughan commented 4 years ago

Most sensible way of converting to POSIXct. Retains clock time. Will be good for {warp} and slide_period() once warp_distance() casts unknown input to POSIXct

UPDATE: I now think that conversion to POSIXct should be backwards compatible. It sort of makes sense if you assume that these partial dates are implicitly UTC. Then you are converting from UTC to the local time zone, so you get the shift. Really this was just a bad choice of default tz = "", it should have been tz = "UTC".

suppressPackageStartupMessages({
  library(timeclass)
  library(zoo)
  library(tsibble)
  library(dint)
})

x <- as.Date("2000-01-01")

# by default, UTC, same clock time
as.POSIXct(as_ym(x))
#> [1] "2000-01-01 UTC"
as.POSIXct(as.yearmon(x))
#> [1] "1999-12-31 19:00:00 EST"
as.POSIXct(yearmonth(x))
#> [1] "1999-12-31 19:00:00 EST"
as.POSIXct(as_date_ym(x))
#> [1] "1999-12-31 19:00:00 EST"

# other implementations dont respect tz arg
as.POSIXct(as_ym(x), tz = "America/Los_Angeles")
#> [1] "2000-01-01 PST"
as.POSIXct(as.yearmon(x), tz = "America/Los_Angeles")
#> [1] "1999-12-31 19:00:00 EST"
as.POSIXct(yearmonth(x), tz = "America/Los_Angeles")
#> [1] "1999-12-31 19:00:00 EST"
as.POSIXct(as_date_ym(x), tz = "America/Los_Angeles")
#> [1] "1999-12-31 19:00:00 EST"

Created on 2020-04-08 by the reprex package (v0.3.0)


DavisVaughan commented 4 years ago

Subtraction is not defined when you subtract a ym from an integer

suppressPackageStartupMessages({
  library(timeclass)
  library(zoo)
  library(tsibble)
  library(dint)
})

x <- as.Date("2000-01-01")

# subtracting a ym is not
1L - as_ym(x)
#> Error: <integer> - <ym> is not permitted
1L - as.yearmon(x)
#> Error in `-.yearmon`(1L, as.yearmon(x)): Can only subtract from yearmon objects
1L - yearmonth(x)
#> [1] "1056 Dec"
1L - as_date_ym(x)
#> Error: `is_date_ym(x)` is not 'TRUE'

Created on 2020-04-08 by the reprex package (v0.3.0)

DavisVaughan commented 4 years ago

Multiplication and division aren't allowed

suppressPackageStartupMessages({
  library(timeclass)
  library(zoo)
  library(tsibble)
  library(dint)
})

x <- as.Date("2000-01-01")

# multiplication and division
2L * as_ym(x)
#> Error: <integer> * <ym> is not permitted
2L * as.yearmon(x) # sure why not?
#> [1] "Jan 4000"
2L * yearmonth(x)
#> Error in Ops.Date(2L, yearmonth(x)): * not defined for "Date" objects
2L * as_date_ym(x)
#> Error in `*.date_xx`(2L, as_date_ym(x)): Operation not supported

2L / as_ym(x)
#> Error: <integer> / <ym> is not permitted
2L / as.yearmon(x) # sure why not?
#> [1] "Jan 0000"
2L / yearmonth(x)
#> Error in Ops.Date(2L, yearmonth(x)): / not defined for "Date" objects
2L / as_date_ym(x)
#> Error in `/.date_xx`(2L, as_date_ym(x)): Operation not supported

Created on 2020-04-08 by the reprex package (v0.3.0)

DavisVaughan commented 4 years ago

OOB subsetting is an error

suppressPackageStartupMessages({
  library(timeclass)
  library(zoo)
  library(tsibble)
  library(dint)
})

x <- as.Date("2000-01-01")

# OOB subsetting
as_ym(x)[2]
#> Error: Can't subset elements that don't exist.
#> x Location 2 doesn't exist.
#> ℹ There are only 1 element.
as.yearmon(x)[2]
#> [1] NA
yearmonth(x)[2]
#> [1] NA
as_date_ym(x)[2]
#> [1] "NA-MNA"

Created on 2020-04-08 by the reprex package (v0.3.0)

DavisVaughan commented 4 years ago

Stupid fast for ym because of how it is internally stored (number of months since 1970-01-01)

suppressPackageStartupMessages({
  library(timeclass)
  library(zoo)
  library(tsibble)
  library(dint)
})

x <- rep(as.Date("2000-01-01"), 1e5)

x_ym <- as_ym(x)
x_yearmon <- as.yearmon(x)
x_yearmonth <- yearmonth(x)
x_date_ym <- as_date_ym(x)

# speed of addition
bench::mark(
  x_ym + 1L,
  x_yearmon + 1L,
  x_yearmonth + 1L,
  x_date_ym + 1L,
  check = FALSE
)
#> Warning: Some expressions had a GC in every iteration; so filtering is disabled.
#> # A tibble: 4 x 6
#>   expression            min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>       <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 x_ym + 1L        225.33µs 305.04µs   2618.    470.01KB     21.8
#> 2 x_yearmon + 1L     1.44ms   1.63ms    422.      3.83MB     47.1
#> 3 x_yearmonth + 1L     82ms  90.25ms      9.91   33.19MB     11.9
#> 4 x_date_ym + 1L    61.58ms  68.75ms     14.6    29.64MB     18.3

Created on 2020-04-08 by the reprex package (v0.3.0)

DavisVaughan commented 4 years ago

Math and Summary functions are not supported

suppressPackageStartupMessages({
  library(timeclass)
  library(zoo)
  library(tsibble)
  library(dint)
})

x <- as.Date("2000-01-01")

x_ym <- as_ym(x)
x_yearmon <- as.yearmon(x)
x_yearmonth <- yearmonth(x)
x_date_ym <- as_date_ym(x)

log(x_ym)
#> Error: `log()` is not supported for <ym>.
log(x_yearmon)
#> [1] "Aug 0007"
log(x_yearmonth)
#> Error in Math.Date(x_yearmonth): log not defined for "Date" objects
log(x_date_ym)
#> [1] "0-M12"

mean(x_ym)
#> Error: `mean()` is not supported for <ym>.
mean(x_yearmon)
#> [1] "Jan 2000"
mean(x_yearmonth)
#> [1] "2000-01-01"
mean(x_date_ym)
#> [1] 200001

Created on 2020-04-08 by the reprex package (v0.3.0)

DavisVaughan commented 4 years ago

Better seq() method

suppressPackageStartupMessages({
  library(timeclass)
  library(zoo)
  library(tsibble)
  library(dint)
})

x <- as.Date("2000-02-01")

x_ym <- as_ym(x)
x_yearmon <- as.yearmon(x)
x_yearmonth <- yearmonth(x)
x_date_ym <- as_date_ym(x)

seq(x_ym, to = x_ym + 20, length.out = 3)
#> <ym[3]>
#> [1] 2000-02 2000-12 2001-10
seq(x_yearmon, to = x_yearmon + 20, length.out = 3) # loses class
#> [1] 2000.083 2010.083 2020.083
seq(x_yearmonth, to = x_yearmonth + 20, length.out = 3) # not allowed
#> Error in bad_by(by): argument "by" is missing, with no default
seq(x_date_ym, to = x_date_ym + 20, length.out = 3) # what?
#>  [1] "2000-M02" "2000-M03" "2000-M04" "2000-M05" "2000-M06" "2000-M07"
#>  [7] "2000-M08" "2000-M09" "2000-M10" "2000-M11" "2000-M12" "2001-M01"
#> [13] "2001-M02" "2001-M03" "2001-M04" "2001-M05" "2001-M06" "2001-M07"
#> [19] "2001-M08" "2001-M09" "2001-M10"

seq(x_ym, by = 5, length.out = 3)
#> <ym[3]>
#> [1] 2000-02 2000-07 2000-12
seq(x_yearmon, by = 5, length.out = 3) # adds years?
#> [1] "Feb 2000" "Feb 2005" "Feb 2010"
seq(x_yearmonth, by = 5, length.out = 3)
#> [1] "2000 Feb" "2000 Jul" "2000 Dec"
seq(x_date_ym, by = 5, length.out = 3) # requires to
#> Error in is_date_ym(to): argument "to" is missing, with no default

Created on 2020-04-09 by the reprex package (v0.3.0)