Unidata / UDUNITS-2

API and utility for arithmetic manipulation of units of physical quantities
http://www.unidata.ucar.edu/software/udunits
Other
59 stars 36 forks source link

Incorrect leap year at 0200-02-29 in udunits #83

Closed kendonB closed 5 years ago

kendonB commented 5 years ago

I found this through the R package units and it causes odd behavior in dates prior to 0200-02-28

library(units)
#> udunits system database from C:/R/Library/3.5/RNetCDF/udunits
x1 <- as_units(1, "seconds since 200-02-28 00:00:00 +00:00")
units(x1) = units:::symbolic_unit("seconds since 1970-01-01 00:00:00 +00:00")
as.POSIXct.numeric(as.numeric(x1), tz = "UTC", origin = as.POSIXct("1970-01-01 00:00:00", 
                                                                   tz = "UTC"))
#> [1] "0200-02-27 00:00:01 UTC"

x2 <- as_units(1, "seconds since 200-03-01 00:00:00 +00:00")
units(x2) = units:::symbolic_unit("seconds since 1970-01-01 00:00:00 +00:00")
as.POSIXct.numeric(as.numeric(x2), tz = "UTC", origin = as.POSIXct("1970-01-01 00:00:00", 
                                                                   tz = "UTC"))
#> [1] "0200-03-01 00:00:01 UTC"

# units thinks there's a leap day there
(as.numeric(x1) - as.numeric(x2))/86400
#> [1] -2

# R does not think there's a leap day there
as.Date("0200-02-29")
#> Error in charToDate(x): character string is not in a standard unambiguous format

Created on 2019-03-02 by the reprex package (v0.2.1.9000)

I came across this problem in real life when using stars::read_ncdf on this file which stores dates with "0000-01-01" as the origin:

mrso_Lmon_FGOALS-g2_historical_r2i1p1_200001-200912.zip

The above code is inside as.POSIXct.units.

https://calendarhome.com/calculate/days-between-2-dates agrees with R and not units. image

kendonB commented 5 years ago

From here: https://www.unidata.ucar.edu/software/udunits/udunits-current/doc/udunits/udunits2lib.html#Time

"You should be aware, however, that the hybrid Gregorian/Julian calendar used by the UDUNITS-2 package cannot be changed. Dates on or after 1582-10-15 are assumed to be Gregorian dates; dates before that are assumed to be Julian dates. In particular, the year 1 BCE is immediately followed by the year 1 CE."