Search code examples
rdatenetcdfnetcdf4unidata

Convert a netcdf time variable to an R date object


I have a netcdf file with a timeseries and the time variable has the following typical metadata:

    double time(time) ;
            time:standard_name = "time" ;
            time:bounds = "time_bnds" ;
            time:units = "days since 1979-1-1 00:00:00" ;
            time:calendar = "standard" ;
            time:axis = "T" ;

Inside R I want to convert the time into an R date object. I achieve this at the moment in a hardwired way by reading the units attribute and splitting the string and using the third entry as my origin (thus assuming the spacing is "days" and the time is 00:00 etc):

require("ncdf4")
f1<-nc_open("file.nc")
time<-ncvar_get(f1,"time")
tunits<-ncatt_get(f1,"time",attname="units")
tustr<-strsplit(tunits$value, " ")
dates<-as.Date(time,origin=unlist(tustr)[3])

This hardwired solution works for my specific example, but I was hoping that there might be a package in R that nicely handles the UNIDATA netcdf date conventions for time units and convert them safely to an R date object?


Solution

  • Your hopes have been met by package CFtime. This package can deal with the CF Metadata Conventions "time" dimension seamlessly, including all defined calendars.

    f1 <- nc_open("file.nc")
    cf <- CFtime(f1$dim$time$units, f1$dim$time$calendar, f1$dim$time$vals)
    dates <- CFtimestamp(cf)
    
    # This works reliably only for 3 of the 9 defined calendars
    dates <- as.Date(dates)
    

    The CFtimestamp() function gives a correct output for all possible dates, including the oddball "2023-02-30" but not "2023-03-31" on a "360_day" calendar. Converting to POSIXct is tricky but do you really need a Date to work with or will a character representation do just fine?