diff --git a/nc_time_axis/__init__.py b/nc_time_axis/__init__.py index b3e0804..e9865d3 100644 --- a/nc_time_axis/__init__.py +++ b/nc_time_axis/__init__.py @@ -81,7 +81,7 @@ def pick_format(self, ndays): def __call__(self, x, pos=0): format_string = self.pick_format(ndays=self.locator.ndays) - dt = cftime.utime(self.time_units, self.calendar).num2date(x) + dt = cftime.num2date(x, self.time_units, self.calendar) return dt.strftime(format_string) @@ -143,9 +143,8 @@ def tick_values(self, vmin, vmax): self.ndays = float(abs(vmax - vmin)) - utime = cftime.utime(self.date_unit, self.calendar) - lower = utime.num2date(vmin) - upper = utime.num2date(vmax) + lower = cftime.num2date(vmin, self.date_unit, self.calendar) + upper = cftime.num2date(vmax, self.date_unit, self.calendar) resolution, n = self.compute_resolution(vmin, vmax, lower, upper) @@ -153,40 +152,75 @@ def tick_values(self, vmin, vmax): # TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as # appropriate. years = self._max_n_locator.tick_values(lower.year, upper.year) - ticks = [cftime.datetime(int(year), 1, 1) for year in years] + ticks = [] + for year in years: + ticks.append(cftime.datetime(int(year), 1, 1, calendar=None)) elif resolution == 'MONTHLY': # TODO START AT THE BEGINNING OF A DECADE/CENTURY/MILLENIUM as # appropriate. months_offset = self._max_n_locator.tick_values(0, n) ticks = [] for offset in months_offset: - year = lower.year + np.floor((lower.month + offset) / 12) - month = ((lower.month + offset) % 12) + 1 - ticks.append(cftime.datetime(int(year), int(month), 1)) + year = int(lower.year + np.floor((lower.month + offset) / 12)) + month = int(((lower.month + offset) % 12) + 1) + ticks.append(cftime.datetime(year, month, 1, calendar=None)) elif resolution == 'DAILY': # TODO: It would be great if this favoured multiples of 7. days = self._max_n_locator_days.tick_values(vmin, vmax) - ticks = [utime.num2date(dt) for dt in days] + ticks = [ + cftime.num2date( + dt, + self.date_unit, + self.calendar + ) for dt in days + ] elif resolution == 'HOURLY': hour_unit = 'hours since 2000-01-01' - hour_utime = cftime.utime(hour_unit, self.calendar) - in_hours = hour_utime.date2num([lower, upper]) + in_hours = cftime.date2num( + [lower, upper], + hour_unit, + self.calendar + ) hours = self._max_n_locator.tick_values(in_hours[0], in_hours[1]) - ticks = [hour_utime.num2date(dt) for dt in hours] + ticks = [ + cftime.num2date( + dt, + hour_unit, + self.calendar + ) for dt in hours + ] elif resolution == 'MINUTELY': minute_unit = 'minutes since 2000-01-01' - minute_utime = cftime.utime(minute_unit, self.calendar) - in_minutes = minute_utime.date2num([lower, upper]) + in_minutes = cftime.date2num( + [lower, upper], + minute_unit, + self.calendar + ) minutes = self._max_n_locator.tick_values(in_minutes[0], in_minutes[1]) - ticks = [minute_utime.num2date(dt) for dt in minutes] + ticks = [ + cftime.num2date( + dt, + minute_unit, + self.calendar + ) for dt in minutes + ] elif resolution == 'SECONDLY': second_unit = 'seconds since 2000-01-01' - second_utime = cftime.utime(second_unit, self.calendar) - in_seconds = second_utime.date2num([lower, upper]) + in_seconds = cftime.date2num( + [lower, upper], + second_unit, + self.calendar + ) seconds = self._max_n_locator.tick_values(in_seconds[0], in_seconds[1]) - ticks = [second_utime.num2date(dt) for dt in seconds] + ticks = [ + cftime.num2date( + dt, + second_unit, + self.calendar + ) for dt in seconds + ] else: msg = 'Resolution {} not implemented yet.'.format(resolution) raise ValueError(msg) @@ -199,7 +233,7 @@ def tick_values(self, vmin, vmax): "standard", ]: ticks = [t for t in ticks if t.year != 0] - return utime.date2num(ticks) + return cftime.date2num(ticks, self.date_unit, self.calendar) class NetCDFTimeConverter(mdates.DateConverter): @@ -265,7 +299,7 @@ def default_units(cls, sample_point, axis): def convert(cls, value, unit, axis): """ Converts value, if it is not already a number or sequence of numbers, - with :func:`cftime.utime().date2num`. + with :func:`cftime.date2num`. """ shape = None @@ -293,15 +327,21 @@ def convert(cls, value, unit, axis): 'CalendarDateTime object must be of type ' '`cftime.datetime`.') - ut = cftime.utime(cls.standard_unit, calendar=first_value.calendar) - if isinstance(value, (CalendarDateTime, cftime.datetime)): value = [value] if isinstance(first_value, CalendarDateTime): - result = ut.date2num([v.datetime for v in value]) + result = cftime.date2num( + [v.datetime for v in value], + cls.standard_unit, + first_value.calendar + ) else: - result = ut.date2num(value) + result = cftime.date2num( + value, + cls.standard_unit, + first_value.calendar + ) if shape is not None: result = result.reshape(shape) diff --git a/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py b/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py index ed48f43..b6f0389 100644 --- a/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py +++ b/nc_time_axis/tests/unit/test_NetCDFTimeDateLocator.py @@ -25,9 +25,12 @@ def check(self, max_n_ticks, num1, num2): locator = NetCDFTimeDateLocator(max_n_ticks=max_n_ticks, calendar=self.calendar, date_unit=self.date_unit) - utime = cftime.utime(self.date_unit, self.calendar) - return locator.compute_resolution(num1, num2, utime.num2date(num1), - utime.num2date(num2)) + return locator.compute_resolution( + num1, + num2, + cftime.num2date(num1, self.date_unit, self.calendar), + cftime.num2date(num2, self.date_unit, self.calendar) + ) def test_one_minute(self): self.assertEqual(self.check(20, 0, 0.0003), @@ -146,9 +149,14 @@ def check(self, max_n_ticks, num1, num2, calendar): 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] + year_ticks = [ + cftime.num2date( + t, + self.date_unit, + calendar + ).year for t in ticks + ] if calendar in self.yr0_remove_calendars: self.assertNotIn(0, year_ticks) else: