From 281eebb2e903e5466da12446a7a5d395a627f6fd Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Fri, 8 Jul 2022 13:58:29 +0100 Subject: [PATCH 1/4] first attempt --- lib/iris/fileformats/pp.py | 2 +- lib/iris/fileformats/pp_load_rules.py | 9 +++++++-- .../fileformats/pp_load_rules/test__epoch_date_hours.py | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/iris/fileformats/pp.py b/lib/iris/fileformats/pp.py index bc35acb3b3..67d7dc095d 100644 --- a/lib/iris/fileformats/pp.py +++ b/lib/iris/fileformats/pp.py @@ -1078,7 +1078,7 @@ def core_data(self): def calendar(self): """Return the calendar of the field.""" # TODO #577 What calendar to return when ibtim.ic in [0, 3] - calendar = cf_units.CALENDAR_STANDARD + calendar = cf_units.CALENDAR_PROLEPTIC_GREGORIAN if self.lbtim.ic == 2: calendar = cf_units.CALENDAR_360_DAY elif self.lbtim.ic == 4: diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index ebccec47ee..facdd35a5a 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -503,6 +503,11 @@ def _new_coord_and_dims( a new (coordinate, dims) pair. """ + if ( + units.is_time_reference() + and units.calendar == cf_units.CALENDAR_PROLEPTIC_GREGORIAN + ): + units = units.change_calendar(cf_units.CALENDAR_STANDARD) bounds = lower_and_upper_bounds if is_vector_operation: dims, points, bounds = _reduce_points_and_bounds(points, bounds) @@ -548,7 +553,7 @@ def _epoch_date_hours_internals(epoch_hours_unit, datetime): if m == 0: # Add a 'January', by changing month=0 to 1. m = 1 - if calendar == cf_units.CALENDAR_STANDARD: + if calendar == cf_units.CALENDAR_PROLEPTIC_GREGORIAN: days_offset += 31 elif calendar == cf_units.CALENDAR_360_DAY: days_offset += 30 @@ -561,7 +566,7 @@ def _epoch_date_hours_internals(epoch_hours_unit, datetime): if y == 0: # Add a 'Year 0', by changing year=0 to 1. y = 1 - if calendar == cf_units.CALENDAR_STANDARD: + if calendar == cf_units.CALENDAR_PROLEPTIC_GREGORIAN: days_in_year_0 = 366 elif calendar == cf_units.CALENDAR_360_DAY: days_in_year_0 = 360 diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__epoch_date_hours.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__epoch_date_hours.py index 2c5d672e14..25923556b9 100644 --- a/lib/iris/tests/unit/fileformats/pp_load_rules/test__epoch_date_hours.py +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__epoch_date_hours.py @@ -30,7 +30,7 @@ class TestEpochHours__standard(tests.IrisTest): def setUp(self): - self.calendar = cf_units.CALENDAR_STANDARD + self.calendar = cf_units.CALENDAR_PROLEPTIC_GREGORIAN self.hrs_unit = Unit("hours since epoch", calendar=self.calendar) def test_1970_1_1(self): From d8d3c5abdae04622425fb04ad7ab058b998f35e8 Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 18 Jan 2023 15:04:47 +0000 Subject: [PATCH 2/4] address saving standard --- lib/iris/fileformats/pp_save_rules.py | 69 +++++++++---------- .../test__convert_time_coords.py | 16 ++++- 2 files changed, 47 insertions(+), 38 deletions(-) diff --git a/lib/iris/fileformats/pp_save_rules.py b/lib/iris/fileformats/pp_save_rules.py index 0369fc9fd0..3c121c5481 100644 --- a/lib/iris/fileformats/pp_save_rules.py +++ b/lib/iris/fileformats/pp_save_rules.py @@ -114,6 +114,11 @@ def _general_time_rules(cube, pp): frt_coord = scalar_coord(cube, "forecast_reference_time") clim_season_coord = scalar_coord(cube, "clim_season") + if time_coord is not None: + time_unit = time_coord.units + if time_unit.calendar == "standard": + time_unit = time_unit.change_calendar("proleptic_gregorian") + cm_time_mean = scalar_cell_method(cube, "mean", "time") cm_time_min = scalar_cell_method(cube, "minimum", "time") cm_time_max = scalar_cell_method(cube, "maximum", "time") @@ -122,7 +127,7 @@ def _general_time_rules(cube, pp): if time_coord is not None and fp_coord is None and frt_coord is None: pp.lbtim.ia = 0 pp.lbtim.ib = 0 - pp.t1 = time_coord.units.num2date(time_coord.points[0]) + pp.t1 = time_unit.num2date(time_coord.points[0]) pp.t2 = cftime.datetime(0, 0, 0, calendar=None, has_year_zero=True) # Forecast. @@ -133,10 +138,8 @@ def _general_time_rules(cube, pp): ): pp.lbtim.ia = 0 pp.lbtim.ib = 1 - pp.t1 = time_coord.units.num2date(time_coord.points[0]) - pp.t2 = time_coord.units.num2date( - time_coord.points[0] - fp_coord.points[0] - ) + pp.t1 = time_unit.num2date(time_coord.points[0]) + pp.t2 = time_unit.num2date(time_coord.points[0] - fp_coord.points[0]) pp.lbft = fp_coord.points[0] # Time mean (non-climatological). @@ -151,8 +154,8 @@ def _general_time_rules(cube, pp): # XXX How do we know *which* time to use if there are more than # one? *Can* there be more than one? pp.lbtim.ib = 2 - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], "hours") if ( @@ -164,8 +167,8 @@ def _general_time_rules(cube, pp): ): # Handle missing forecast period using time and forecast ref time. pp.lbtim.ib = 2 - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) stop = time_coord.units.convert( time_coord.bounds[0, 1], "hours since epoch" ) @@ -181,8 +184,8 @@ def _general_time_rules(cube, pp): and cm_time_mean is not None ): pp.lbtim.ib = 2 - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) if ( time_coord is not None @@ -238,12 +241,8 @@ def _general_time_rules(cube, pp): pp.lbtim.ia = int(cm_time_max.intervals[0][:-5]) if time_coord is not None and time_coord.has_bounds(): - lower_bound_yr = time_coord.units.num2date( - time_coord.bounds[0, 0] - ).year - upper_bound_yr = time_coord.units.num2date( - time_coord.bounds[0, 1] - ).year + lower_bound_yr = time_unit.num2date(time_coord.bounds[0, 0]).year + upper_bound_yr = time_unit.num2date(time_coord.bounds[0, 1]).year else: lower_bound_yr = None upper_bound_yr = None @@ -261,8 +260,8 @@ def _general_time_rules(cube, pp): # Climatological time mean - single year. pp.lbtim.ia = 0 pp.lbtim.ib = 2 - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], "hours") elif ( @@ -278,19 +277,19 @@ def _general_time_rules(cube, pp): # Climatological time mean - spanning years - djf. pp.lbtim.ia = 0 pp.lbtim.ib = 3 - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) if pp.t1.month == 12: pp.t1 = cftime.datetime(pp.t1.year, 12, 1, 0, 0, 0) else: pp.t1 = cftime.datetime(pp.t1.year - 1, 12, 1, 0, 0, 0) pp.t2 = cftime.datetime(pp.t2.year, 3, 1, 0, 0, 0) _conditional_warning( - time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + time_coord.bounds[0, 0] != time_unit.date2num(pp.t1), "modified t1 for climatological seasonal mean", ) _conditional_warning( - time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + time_coord.bounds[0, 1] != time_unit.date2num(pp.t2), "modified t2 for climatological seasonal mean", ) pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], "hours") @@ -309,16 +308,16 @@ def _general_time_rules(cube, pp): pp.lbtim.ia = 0 pp.lbtim.ib = 3 # TODO: wut? - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) pp.t1 = cftime.datetime(pp.t1.year, 3, 1, 0, 0, 0) pp.t2 = cftime.datetime(pp.t2.year, 6, 1, 0, 0, 0) _conditional_warning( - time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + time_coord.bounds[0, 0] != time_unit.date2num(pp.t1), "modified t1 for climatological seasonal mean", ) _conditional_warning( - time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + time_coord.bounds[0, 1] != time_unit.date2num(pp.t2), "modified t2 for climatological seasonal mean", ) pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], "hours") @@ -337,16 +336,16 @@ def _general_time_rules(cube, pp): pp.lbtim.ia = 0 pp.lbtim.ib = 3 # TODO: wut? - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) pp.t1 = cftime.datetime(pp.t1.year, 6, 1, 0, 0, 0) pp.t2 = cftime.datetime(pp.t2.year, 9, 1, 0, 0, 0) _conditional_warning( - time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + time_coord.bounds[0, 0] != time_unit.date2num(pp.t1), "modified t1 for climatological seasonal mean", ) _conditional_warning( - time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + time_coord.bounds[0, 1] != time_unit.date2num(pp.t2), "modified t2 for climatological seasonal mean", ) pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], "hours") @@ -365,16 +364,16 @@ def _general_time_rules(cube, pp): pp.lbtim.ia = 0 pp.lbtim.ib = 3 # TODO: wut? - pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0]) - pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1]) + pp.t1 = time_unit.num2date(time_coord.bounds[0, 0]) + pp.t2 = time_unit.num2date(time_coord.bounds[0, 1]) pp.t1 = cftime.datetime(pp.t1.year, 9, 1, 0, 0, 0) pp.t2 = cftime.datetime(pp.t2.year, 12, 1, 0, 0, 0) _conditional_warning( - time_coord.bounds[0, 0] != time_coord.units.date2num(pp.t1), + time_coord.bounds[0, 0] != time_unit.date2num(pp.t1), "modified t1 for climatological seasonal mean", ) _conditional_warning( - time_coord.bounds[0, 1] != time_coord.units.date2num(pp.t2), + time_coord.bounds[0, 1] != time_unit.date2num(pp.t2), "modified t2 for climatological seasonal mean", ) pp.lbft = fp_coord.units.convert(fp_coord.bounds[0, 1], "hours") diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py index cf147e5928..8e95f04afb 100644 --- a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py @@ -13,7 +13,7 @@ # importing anything else. import iris.tests as tests # isort:skip -from cf_units import CALENDAR_360_DAY, CALENDAR_STANDARD, Unit +from cf_units import CALENDAR_360_DAY, CALENDAR_PROLEPTIC_GREGORIAN, Unit from cftime import datetime as nc_datetime import numpy as np @@ -38,14 +38,24 @@ def _lbcode(value=None, ix=None, iy=None): return result -_EPOCH_HOURS_UNIT = Unit("hours since epoch", calendar=CALENDAR_STANDARD) +_EPOCH_HOURS_UNIT = Unit( + "hours since epoch", calendar=CALENDAR_PROLEPTIC_GREGORIAN +) _HOURS_UNIT = Unit("hours") class TestLBTIMx0x_SingleTimepoint(TestField): def _check_timepoint(self, lbcode, expect_match=True): lbtim = _lbtim(ib=0, ic=1) - t1 = nc_datetime(1970, 1, 1, hour=6, minute=0, second=0) + t1 = nc_datetime( + 1970, + 1, + 1, + hour=6, + minute=0, + second=0, + calendar="proleptic_gregorian", + ) t2 = nc_datetime( 0, 0, 0, calendar=None, has_year_zero=True ) # not used in result From dde873d0b569d67bbefc7e084b8788c6d8b314db Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Wed, 18 Jan 2023 16:06:39 +0000 Subject: [PATCH 3/4] more test fixes --- lib/iris/fileformats/pp_load_rules.py | 4 +- .../tests/unit/fileformats/pp/test_PPField.py | 2 +- .../test__convert_time_coords.py | 92 ++++++++++--------- 3 files changed, 54 insertions(+), 44 deletions(-) diff --git a/lib/iris/fileformats/pp_load_rules.py b/lib/iris/fileformats/pp_load_rules.py index facdd35a5a..b3676d02c1 100644 --- a/lib/iris/fileformats/pp_load_rules.py +++ b/lib/iris/fileformats/pp_load_rules.py @@ -507,7 +507,9 @@ def _new_coord_and_dims( units.is_time_reference() and units.calendar == cf_units.CALENDAR_PROLEPTIC_GREGORIAN ): - units = units.change_calendar(cf_units.CALENDAR_STANDARD) + units = cf_units.Unit( + "hours since epoch", calendar=cf_units.CALENDAR_STANDARD + ) bounds = lower_and_upper_bounds if is_vector_operation: dims, points, bounds = _reduce_points_and_bounds(points, bounds) diff --git a/lib/iris/tests/unit/fileformats/pp/test_PPField.py b/lib/iris/tests/unit/fileformats/pp/test_PPField.py index 5e2bbcaa2c..b3f8bcbe55 100644 --- a/lib/iris/tests/unit/fileformats/pp/test_PPField.py +++ b/lib/iris/tests/unit/fileformats/pp/test_PPField.py @@ -143,7 +143,7 @@ class Test_calendar(tests.IrisTest): def test_greg(self): field = DummyPPField() field.lbtim = SplittableInt(1, {"ia": 2, "ib": 1, "ic": 0}) - self.assertEqual(field.calendar, "standard") + self.assertEqual(field.calendar, "proleptic_gregorian") def test_360(self): field = DummyPPField() diff --git a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py index 8e95f04afb..1040a2ecce 100644 --- a/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py +++ b/lib/iris/tests/unit/fileformats/pp_load_rules/test__convert_time_coords.py @@ -13,7 +13,12 @@ # importing anything else. import iris.tests as tests # isort:skip -from cf_units import CALENDAR_360_DAY, CALENDAR_PROLEPTIC_GREGORIAN, Unit +from cf_units import ( + CALENDAR_360_DAY, + CALENDAR_PROLEPTIC_GREGORIAN, + CALENDAR_STANDARD, + Unit, +) from cftime import datetime as nc_datetime import numpy as np @@ -38,9 +43,10 @@ def _lbcode(value=None, ix=None, iy=None): return result -_EPOCH_HOURS_UNIT = Unit( +_EPOCH_HOURS_UNIT_IN = Unit( "hours since epoch", calendar=CALENDAR_PROLEPTIC_GREGORIAN ) +_EPOCH_HOURS_UNIT_OUT = Unit("hours since epoch", calendar=CALENDAR_STANDARD) _HOURS_UNIT = Unit("hours") @@ -63,7 +69,7 @@ def _check_timepoint(self, lbcode, expect_match=True): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -74,7 +80,7 @@ def _check_timepoint(self, lbcode, expect_match=True): DimCoord( 24 * 0.25, standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ), None, ) @@ -104,7 +110,7 @@ def _check_forecast(self, lbcode, expect_match=True): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -123,7 +129,7 @@ def _check_forecast(self, lbcode, expect_match=True): DimCoord( 24 * 9.25, standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ), None, ), @@ -131,7 +137,7 @@ def _check_forecast(self, lbcode, expect_match=True): DimCoord( 24 * 8.125, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ), None, ), @@ -156,7 +162,7 @@ def test_exact_hours(self): coords_and_dims = _convert_time_coords( lbcode=_lbcode(1), lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=None, @@ -173,7 +179,7 @@ def test_not_exact_hours(self): coords_and_dims = _convert_time_coords( lbcode=_lbcode(1), lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=None, @@ -194,7 +200,7 @@ def _check_period(self, lbcode, expect_match=True): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -205,7 +211,7 @@ def _check_period(self, lbcode, expect_match=True): DimCoord( 24 * 9.125 - 2.0, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ), None, ), @@ -221,7 +227,7 @@ def _check_period(self, lbcode, expect_match=True): ( DimCoord( standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, points=[24 * 8.625], bounds=[24 * 8.125, 24 * 9.125], ), @@ -253,7 +259,7 @@ def _check_yearly(self, lbcode, expect_match=True): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -267,7 +273,7 @@ def _check_yearly(self, lbcode, expect_match=True): DimCoord( [t2_hours - lbft], standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ), None, ), @@ -283,7 +289,7 @@ def _check_yearly(self, lbcode, expect_match=True): ( DimCoord( standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, points=[t2_hours], bounds=[t1_hours, t2_hours], ), @@ -314,7 +320,7 @@ def test_(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -332,7 +338,7 @@ def test_unrecognised(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -355,7 +361,7 @@ def test(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -366,7 +372,7 @@ def test(self): DimCoord( [t2_hours - lbft], standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ), None, ) @@ -391,7 +397,7 @@ def test_t1_list(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_OUT, t1=t1, t2=t2, lbft=lbft, @@ -400,7 +406,9 @@ def test_t1_list(self): # Expected coords. time_coord = DimCoord( - (24 * 8) + 3 + hours, standard_name="time", units=_EPOCH_HOURS_UNIT + (24 * 8) + 3 + hours, + standard_name="time", + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [(time_coord, (0,))] self.assertCoordsAndDimsListsMatch(coords_and_dims, expected) @@ -427,7 +435,7 @@ def test_t1_list_t2_scalar(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -443,12 +451,12 @@ def test_t1_list_t2_scalar(self): time_coord = DimCoord( (24 * 8) + 3 + forecast_period_in_hours, standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) fref_time_coord = DimCoord( (24 * 8) + 3, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [ (fp_coord, (0,)), @@ -480,7 +488,7 @@ def test_t1_and_t2_list(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -497,12 +505,12 @@ def test_t1_and_t2_list(self): time_coord = DimCoord( (24 * 8) + 3 + forecast_period_in_hours, standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) fref_time_coord = DimCoord( (24 * 8) + 3, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [ (fp_coord, (0,)), @@ -530,7 +538,7 @@ def test_t1_and_t2_orthogonal_lists(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -548,13 +556,13 @@ def test_t1_and_t2_orthogonal_lists(self): ) points = (years - 1970) * 24 * 365 + (24 * 8) + 12 time_coord = DimCoord( - points, standard_name="time", units=_EPOCH_HOURS_UNIT + points, standard_name="time", units=_EPOCH_HOURS_UNIT_OUT ) points = (24 * 8) + hours fref_time_coord = DimCoord( points, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [ (fp_coord, (0, 1)), # Spans dims 0 and 1. @@ -587,7 +595,7 @@ def test_t1_multi_dim_list_t2_scalar(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -612,12 +620,12 @@ def test_t1_multi_dim_list_t2_scalar(self): for year in years ], standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) fref_time_coord = DimCoord( (24 * 8) + 3, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [ (fp_coord, (0, 1)), @@ -651,7 +659,7 @@ def test_t1_and_t2_nparrays(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -668,12 +676,12 @@ def test_t1_and_t2_nparrays(self): time_coord = DimCoord( (24 * 8) + 3 + forecast_period_in_hours, standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) fref_time_coord = DimCoord( (24 * 8) + 3, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [ (fp_coord, (0,)), @@ -698,7 +706,7 @@ def test_t1_list_t2_scalar(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -723,14 +731,14 @@ def test_t1_list_t2_scalar(self): time_coord = AuxCoord( points, standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, bounds=bounds, ) points = 10 * 24 + 9 - lbft fref_time_coord = DimCoord( points, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [ (fp_coord, (0,)), @@ -755,7 +763,7 @@ def test_t1_scalar_t2_list(self): coords_and_dims = _convert_time_coords( lbcode=lbcode, lbtim=lbtim, - epoch_hours_unit=_EPOCH_HOURS_UNIT, + epoch_hours_unit=_EPOCH_HOURS_UNIT_IN, t1=t1, t2=t2, lbft=lbft, @@ -786,13 +794,13 @@ def test_t1_scalar_t2_list(self): time_coord = AuxCoord( points, standard_name="time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, bounds=bounds, ) fref_time_coord = DimCoord( points - lbft, standard_name="forecast_reference_time", - units=_EPOCH_HOURS_UNIT, + units=_EPOCH_HOURS_UNIT_OUT, ) expected = [ (fp_coord, (0,)), From 9c91af0cdcd1829bbd4acaec3822017c1b8c8b2e Mon Sep 17 00:00:00 2001 From: Ruth Comer Date: Thu, 26 Jan 2023 14:08:52 +0000 Subject: [PATCH 4/4] update save calendar rules --- lib/iris/fileformats/pp_save_rules.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/iris/fileformats/pp_save_rules.py b/lib/iris/fileformats/pp_save_rules.py index 3c121c5481..b9e4ac5ba2 100644 --- a/lib/iris/fileformats/pp_save_rules.py +++ b/lib/iris/fileformats/pp_save_rules.py @@ -397,7 +397,7 @@ def _calendar_rules(cube, pp): if time_coord is not None: if time_coord.units.calendar == "360_day": pp.lbtim.ic = 2 - elif time_coord.units.calendar == "standard": + elif time_coord.units.calendar in ["standard", "proleptic_gregorian"]: pp.lbtim.ic = 1 elif time_coord.units.calendar == "365_day": pp.lbtim.ic = 4