|
5 | 5 | from narwhals._compliant import LazyExprNamespace |
6 | 6 | from narwhals._compliant.any_namespace import DateTimeNamespace |
7 | 7 | from narwhals._constants import MS_PER_SECOND, NS_PER_SECOND, US_PER_SECOND |
8 | | -from narwhals._duration import parse_interval_string |
| 8 | +from narwhals._duration import Interval |
9 | 9 | from narwhals._pandas_like.utils import ( |
10 | | - UNIT_DICT, |
| 10 | + ALIAS_DICT, |
11 | 11 | calculate_timestamp_date, |
12 | 12 | calculate_timestamp_datetime, |
13 | 13 | native_to_narwhals_dtype, |
@@ -154,9 +154,22 @@ def total_nanoseconds(self) -> DaskExpr: |
154 | 154 | ) |
155 | 155 |
|
156 | 156 | def truncate(self, every: str) -> DaskExpr: |
157 | | - multiple, unit = parse_interval_string(every) |
| 157 | + interval = Interval.parse(every) |
| 158 | + unit = interval.unit |
158 | 159 | if unit in {"mo", "q", "y"}: |
159 | | - msg = f"Truncating to {unit} is not supported yet for dask." |
| 160 | + msg = f"Truncating to {unit} is not yet supported for dask." |
160 | 161 | raise NotImplementedError(msg) |
161 | | - freq = f"{multiple}{UNIT_DICT.get(unit, unit)}" |
| 162 | + freq = f"{interval.multiple}{ALIAS_DICT.get(unit, unit)}" |
162 | 163 | return self.compliant._with_callable(lambda expr: expr.dt.floor(freq), "truncate") |
| 164 | + |
| 165 | + def offset_by(self, by: str) -> DaskExpr: |
| 166 | + def func(s: dx.Series, by: str) -> dx.Series: |
| 167 | + interval = Interval.parse_no_constraints(by) |
| 168 | + unit = interval.unit |
| 169 | + if unit in {"y", "q", "mo", "d", "ns"}: |
| 170 | + msg = f"Offsetting by {unit} is not yet supported for dask." |
| 171 | + raise NotImplementedError(msg) |
| 172 | + offset = interval.to_timedelta() |
| 173 | + return s.add(offset) |
| 174 | + |
| 175 | + return self.compliant._with_callable(func, "offset_by", by=by) |
0 commit comments