Skip to content

Commit

Permalink
feat(duckdb): implement strftime
Browse files Browse the repository at this point in the history
  • Loading branch information
cpcloud committed May 23, 2022
1 parent 4be98de commit aebc252
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 6 deletions.
14 changes: 14 additions & 0 deletions ibis/backends/duckdb/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,19 @@ def _regex_extract(t, expr):
return result


def _strftime(t, expr):
op = expr.op()
format_str = op.format_str
if not isinstance(format_str_op := format_str.op(), ops.Literal):
raise TypeError(
"DuckDB format_str must be a literal `str`; "
f"got {type(format_str)}"
)
return sa.func.strftime(
t.translate(op.arg), sa.text(repr(format_str_op.value))
)


operation_registry.update(
{
ops.ArrayColumn: _array_column,
Expand Down Expand Up @@ -173,6 +186,7 @@ def _regex_extract(t, expr):
lambda arg: sa.func.approx_quantile(arg, sa.text(str(0.5)))
),
ops.HLLCardinality: reduction(sa.func.approx_count_distinct),
ops.Strftime: _strftime,
}
)

Expand Down
37 changes: 31 additions & 6 deletions ibis/backends/tests/test_temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,15 +467,40 @@ def test_interval_add_cast_column(backend, alltypes, df):


@pytest.mark.parametrize(
('ibis_pattern', 'pandas_pattern'), [('%Y%m%d', '%Y%m%d')]
('expr_fn', 'pandas_pattern'),
[
param(
lambda t: t.timestamp_col.strftime('%Y%m%d').name("formatted"),
'%Y%m%d',
id="literal_format_str",
),
param(
lambda t: (
t.mutate(suffix="%d")
.select(
[
lambda t: t.timestamp_col.strftime(
"%Y%m" + t.suffix
).name("formatted")
]
)
.formatted
),
'%Y%m%d',
marks=[
pytest.mark.notimpl(["dask", "pandas", "postgres"]),
pytest.mark.notyet(["duckdb"]),
],
id="column_format_str",
),
],
)
@pytest.mark.notimpl(["datafusion", "duckdb", "impala"])
def test_strftime(backend, con, alltypes, df, ibis_pattern, pandas_pattern):
expr = alltypes.timestamp_col.strftime(ibis_pattern)
expected = df.timestamp_col.dt.strftime(pandas_pattern)
@pytest.mark.notimpl(["datafusion", "impala"])
def test_strftime(backend, alltypes, df, expr_fn, pandas_pattern):
expr = expr_fn(alltypes)
expected = df.timestamp_col.dt.strftime(pandas_pattern).rename("formatted")

result = expr.execute()
expected = backend.default_series_rename(expected)
backend.assert_series_equal(result, expected)


Expand Down

0 comments on commit aebc252

Please sign in to comment.