diff --git a/nc_time_axis/__init__.py b/nc_time_axis/__init__.py index ccb8d87..b3e0804 100644 --- a/nc_time_axis/__init__.py +++ b/nc_time_axis/__init__.py @@ -190,7 +190,15 @@ def tick_values(self, vmin, vmax): else: msg = 'Resolution {} not implemented yet.'.format(resolution) raise ValueError(msg) - + # Some calenders do not allow a year 0. + # Remove ticks to avoid raising an error. + if self.calendar in [ + "proleptic_gregorian", + "gregorian", + "julian", + "standard", + ]: + ticks = [t for t in ticks if t.year != 0] return utime.date2num(ticks) diff --git a/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py b/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py index 48ba8bd..ed48f43 100644 --- a/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py +++ b/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py @@ -115,5 +115,45 @@ def test_yearly(self): self.check(5, 0, 5*365), [31., 485., 942., 1399., 1856.]) +class Test_tick_values_yr0(unittest.TestCase): + def setUp(self): + self.date_unit = 'days since 0001-01-01 00:00' + self.all_calendars = [ + 'standard', + 'gregorian', + 'proleptic_gregorian', + 'noleap', + '365_day', + '360_day', + 'julian', + 'all_leap', + '366_day', + ] + self.yr0_remove_calendars = [ + 'proleptic_gregorian', + 'gregorian', + 'julian', + 'standard', + ] + + def check(self, max_n_ticks, num1, num2, calendar): + locator = NetCDFTimeDateLocator( + max_n_ticks=max_n_ticks, calendar=calendar, + date_unit=self.date_unit + ) + return locator.tick_values(num1, num2) + + def test_yearly_yr0_remove(self): + for calendar in self.all_calendars: + # convert values to dates, check that none of them has year 0 + num2date = cftime.utime(self.date_unit, calendar).num2date + ticks = self.check(5, 0, 100 * 365, calendar) + year_ticks = [num2date(t).year for t in ticks] + if calendar in self.yr0_remove_calendars: + self.assertNotIn(0, year_ticks) + else: + self.assertIn(0, year_ticks) + + if __name__ == "__main__": unittest.main()