Skip to content

Error message on CF convention of standard_name in time axis attributes #1245

@larsbuntemeyer

Description

@larsbuntemeyer

Version of compliance checker running:
5.4.2

Describe the checker this affects:
CF checkers

Attach a minimal CDL or NetCDF file which is able to reproduce the issue

netcdf example_timeseries_cf_1_11 {
dimensions:
        time = 24 ;
variables:
        double air_temperature(time) ;
                air_temperature:_FillValue = -9999. ;
                air_temperature:standard_name = "air_temperature" ;
                air_temperature:long_name = "Air temperature" ;
                air_temperature:units = "K" ;
                air_temperature:coordinates = "time lat lon" ;
        int64 time(time) ;
                time:long_name = "Time of measurement" ;
                time:axis = "T" ;
                time:units = "seconds since 1970-01-01" ;
                time:calendar = "gregorian" ;
        double lat ;
                lat:_FillValue = NaN ;
                lat:standard_name = "latitude" ;
                lat:long_name = "Station latitude" ;
                lat:units = "degrees_north" ;
                lat:axis = "Y" ;
        double lon ;
                lon:_FillValue = NaN ;
                lon:standard_name = "longitude" ;
                lon:long_name = "Station longitude" ;
                lon:units = "degrees_east" ;
                lon:axis = "X" ;
        string station ;
                station:long_name = "Station Identifier" ;

// global attributes:
                :title = "Example CF-1.11 Time Series Dataset" ;
                :summary = "Synthetic single-station hourly air temperature time series for CF compliance checking." ;
                :institution = "Example Organization" ;
                :source = "Synthetic generation with xarray" ;
                :history = "Created 2025-09-21T18:21:58.371791Z by xarray" ;
                :references = "https://cfconventions.org/" ;
                :Conventions = "CF-1.11" ;
                :featureType = "timeSeries" ;
                :geospatial_lat_min = 42. ;
                :geospatial_lat_max = 42. ;
                :geospatial_lon_min = -71. ;
                :geospatial_lon_max = -71. ;
                :time_coverage_start = "2025-01-01T00:00:00Z" ;
                :time_coverage_end = "2025-01-01T23:00:00Z" ;
                :coordinates = "station" ;
}

To Reproduce:

# Create a simple CF-1.11 compliant time series NetCDF file with xarray
import numpy as np
import pandas as pd
import xarray as xr
from datetime import datetime, timezone

# Configuration
n_time = 24  # 24 hourly samples
start_time = "2025-01-01"
station_id = "station01"
output_path = "example_timeseries_cf_1_11.nc"

# Create a time coordinate (naive UTC datetimes; CF assumes UTC if no timezone)
time = pd.date_range(start_time, periods=n_time, freq="H")

# Generate example data (air temperature in Kelvin)
rng = np.random.default_rng(seed=42)
air_temperature_K = 273.15 + 5 + 2 * np.sin(np.linspace(0, 2 * np.pi, n_time)) + rng.normal(0, 0.3, n_time)

# Build Dataset
# We model a single-station timeSeries feature: dimensions (time, station)
ds = xr.Dataset(
    data_vars={
        "air_temperature": ("time", air_temperature_K, {
            "standard_name": "air_temperature",
            "long_name": "Air temperature",
            "units": "K",
            "coordinates": "time lat lon",
        })
    },
    coords={
        "time": ("time", time, {
          #  "standard_name": "time",
            "long_name": "Time of measurement",
            "axis": "T"
        }),
        # Represent the station as scalar lat/lon coordinates (1D with length 1 is also acceptable)
        "lat": ((), 42.0, {  # scalar coordinate
            "standard_name": "latitude",
            "long_name": "Station latitude",
            "units": "degrees_north",
            "axis": "Y"
        }),
        "lon": ((), -71.0, {
            "standard_name": "longitude",
            "long_name": "Station longitude",
            "units": "degrees_east",
            "axis": "X"
        }),
        "station": ((), station_id, {"long_name": "Station Identifier"}),
    },
    attrs={
        "title": "Example CF-1.11 Time Series Dataset",
        "summary": "Synthetic single-station hourly air temperature time series for CF compliance checking.",
        "institution": "Example Organization",
        "source": "Synthetic generation with xarray",
        "history": f"Created {datetime.utcnow().isoformat()}Z by xarray",
        "references": "https://cfconventions.org/",
        "Conventions": "CF-1.11",
        "featureType": "timeSeries",
        # ACDD geospatial + temporal summary (optional but useful)
        "geospatial_lat_min": 42.0,
        "geospatial_lat_max": 42.0,
        "geospatial_lon_min": -71.0,
        "geospatial_lon_max": -71.0,
        "time_coverage_start": time[0].isoformat() + "Z",
        "time_coverage_end": time[-1].isoformat() + "Z",
    }
)

# Explicit encodings for CF-compliant time (numeric since epoch) & fill values if needed
encoding = {
    "time": {"units": "seconds since 1970-01-01 00:00:00", "calendar": "gregorian"},
    "air_temperature": {"_FillValue": -9999.0}
}

# Write NetCDF file
ds.to_netcdf(output_path, format="NETCDF4", encoding=encoding)

print(f"Wrote CF-1.12 example file: {output_path}")
print(ds)

command

compliance-checker -t cf:1.11 example_timeseries_cf_1_11.nc

Describe the issue below:
The example above throws the following error:

                                     Errors                                     
--------------------------------------------------------------------------------
§5.1 Independent Latitude, Longitude, Vertical, and Time Axes
* Coordinate variable 'time' should have standard_name='time', found: 'None'

From my understanding of the CF convention regarding relative time axis, this should only be a warning, because

A reference time coordinate is identifiable from its units string alone.

it is only optional to provide a standard name for the time axis:

Optionally, the time coordinate may be indicated additionally by providing the standard_name attribute with an appropriate value, and/or the axis attribute with the value T.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions