def cftime_end_time(date, freq): """Get the cftime.datetime for the end of a period. As we are not supplying actual period objects, assumptions regarding the period are made based on the given freq. IMPORTANT NOTE: this function cannot be used on greater-than-day freq that start at the beginning of a month, e.g. 'MS', 'QS', 'AS' -- this mirrors pandas behavior. Parameters ---------- date : cftime.datetime The original datetime object as a proxy representation for period. freq : str String specifying the frequency/offset such as 'MS', '2D', 'H', or '3T' Returns ------- cftime.datetime The ending datetime of the period inferred from date and freq. """ freq = to_offset(freq) if isinstance(freq, (YearBegin, QuarterBegin, MonthBegin)): raise ValueError("Invalid frequency: " + freq.rule_code()) if isinstance(freq, YearEnd): mod_freq = YearBegin(n=freq.n, month=freq.month) elif isinstance(freq, QuarterEnd): mod_freq = QuarterBegin(n=freq.n, month=freq.month) elif isinstance(freq, MonthEnd): mod_freq = MonthBegin(n=freq.n) else: mod_freq = freq return cftime_start_time(date + mod_freq, freq) - pydt.timedelta(microseconds=1)
def test_to_offset_quarter(month_label, month_int, multiple, offset_str): freq = offset_str offset_type = _QUARTER_OFFSET_TYPES[offset_str] if month_label: freq = "-".join([freq, month_label]) if multiple: freq = f"{multiple}{freq}" result = to_offset(freq) if multiple and month_int: expected = offset_type(n=multiple, month=month_int) elif multiple: if month_int: expected = offset_type(n=multiple) else: if offset_type == QuarterBegin: expected = offset_type(n=multiple, month=1) elif offset_type == QuarterEnd: expected = offset_type(n=multiple, month=12) elif month_int: expected = offset_type(month=month_int) else: if offset_type == QuarterBegin: expected = offset_type(month=1) elif offset_type == QuarterEnd: expected = offset_type(month=12) assert result == expected
def test_to_offset_annual(month_label, month_int, multiple, offset_str): freq = offset_str offset_type = _ANNUAL_OFFSET_TYPES[offset_str] if month_label: freq = '-'.join([freq, month_label]) if multiple: freq = '{}'.format(multiple) + freq result = to_offset(freq) if multiple and month_int: expected = offset_type(n=multiple, month=month_int) elif multiple: expected = offset_type(n=multiple) elif month_int: expected = offset_type(month=month_int) else: expected = offset_type() assert result == expected
def test_to_offset_annual(month_label, month_int, multiple, offset_str): freq = offset_str offset_type = _ANNUAL_OFFSET_TYPES[offset_str] if month_label: freq = '-'.join([freq, month_label]) if multiple: freq = '{}'.format(multiple) + freq result = to_offset(freq) if multiple and month_int: expected = offset_type(n=multiple, month=month_int) elif multiple: expected = offset_type(n=multiple) elif month_int: expected = offset_type(month=month_int) else: expected = offset_type() assert result == expected
def shift_cftime_singular(cftime, n, freq): """Shifts a singular ``cftime`` by the desired frequency. This directly pulls the ``shift`` method from ``CFTimeIndex`` in ``xarray``. This is useful if you need to shift a singular ``cftime`` by some offset, but are not working with a full ``CFTimeIndex``. Args: cftime (``cftime``): ``cftime`` object to shift. n (int): Number of steps to shift by. freq (str): Frequency string, per ``pandas`` convention. See: https://github.com/pydata/xarray/blob/master/xarray/coding/cftimeindex.py#L376. """ if not isinstance(n, int): raise TypeError(f"'n' must be an int, got {n}.") if not isinstance(freq, str): raise TypeError(f"'freq' must be a str, got {freq}.") return cftime + n * to_offset(freq)
def test_to_offset_offset_input(offset): assert to_offset(offset) == offset
def test_invalid_to_offset_str(freq): with pytest.raises(ValueError): to_offset(freq)
def test_to_offset_sub_annual(freq, expected): assert to_offset(freq) == expected
def test_invalid_to_offset_str(freq): with pytest.raises(ValueError): to_offset(freq)
def test_to_offset_sub_annual(freq, expected): assert to_offset(freq) == expected
def test_to_offset_offset_input(offset): assert to_offset(offset) == offset