Skip to content

Commit

Permalink
feat(mysql): implement StringToTimestamp
Browse files Browse the repository at this point in the history
Added test_string_to_timestamp for general backend.
  • Loading branch information
anjakefala authored and cpcloud committed Jul 9, 2022
1 parent 010abf1 commit 169250f
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
13 changes: 13 additions & 0 deletions ibis/backends/mysql/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,18 @@ def _timestamp_diff(t, expr):
return sa.func.timestampdiff(sa.text('SECOND'), sa_right, sa_left)


def _string_to_timestamp(t, expr):
op = expr.op()
sa_arg = t.translate(op.arg)
sa_format_str = t.translate(op.format_str)
if (op.timezone is not None) and op.timezone.op().value != "UTC":
raise com.UnsupportedArgumentError(
'MySQL backend only supports timezone UTC for converting'
'string to timestamp.'
)
return sa.func.str_to_date(sa_arg, sa_format_str)


def _literal(_, expr):
if isinstance(expr, ir.IntervalScalar):
if expr.type().unit in {'ms', 'ns'}:
Expand Down Expand Up @@ -190,6 +202,7 @@ def _find_in_set(t, expr):
ops.TimestampAdd: fixed_arity(operator.add, 2),
ops.TimestampSub: fixed_arity(operator.sub, 2),
ops.TimestampDiff: _timestamp_diff,
ops.StringToTimestamp: _string_to_timestamp,
ops.DateTruncate: _truncate,
ops.TimestampTruncate: _truncate,
ops.IntervalFromInteger: _interval_from_integer,
Expand Down
72 changes: 71 additions & 1 deletion ibis/backends/tests/test_temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from pytest import param

import ibis
import ibis.common.exceptions as com
import ibis.expr.datatypes as dt
from ibis.backends.pandas.execution.temporal import day_name

Expand Down Expand Up @@ -563,7 +564,7 @@ def test_strftime(backend, alltypes, df, expr_fn, pandas_pattern):
],
)
@pytest.mark.notimpl(["datafusion", "mysql", "postgres", "sqlite"])
def test_to_timestamp(backend, con, unit):
def test_integer_to_timestamp(backend, con, unit):
backend_unit = backend.returned_timestamp_unit
factor = unit_factors[unit]

Expand All @@ -579,6 +580,75 @@ def test_to_timestamp(backend, con, unit):
assert result == expected


@pytest.mark.parametrize(
'fmt, timezone',
[
# "11/01/10" - "month/day/year"
param(
'%m/%d/%y',
"UTC",
id="mysql_format",
marks=pytest.mark.never(
["pyspark"], reason="datetime formatting style not supported"
),
),
param(
'MM/dd/yy',
"UTC",
id="pyspark_format",
marks=pytest.mark.never(
["mysql"], reason="datetime formatting style not supported"
),
),
],
)
@pytest.mark.notimpl(
[
'dask',
'pandas',
'postgres',
'duckdb',
'clickhouse',
'sqlite',
'impala',
'datafusion',
]
)
def test_string_to_timestamp(backend, con, fmt, timezone):
table = con.table('functional_alltypes')
result = table.mutate(
date=table.date_string_col.to_timestamp(fmt, timezone)
).execute()

# TEST: do we get the same date out, that we put in?
# format string assumes that we are using pandas' strftime
for i, val in enumerate(result["date"]):
assert val.strftime("%m/%d/%y") == result["date_string_col"][i]


@pytest.mark.notimpl(
[
'dask',
'pandas',
'postgres',
'duckdb',
'clickhouse',
'sqlite',
'impala',
'datafusion',
]
)
def test_string_to_timestamp_tz_error(backend, con):
table = con.table('functional_alltypes')

with pytest.raises(com.UnsupportedArgumentError):
table.mutate(
date=table.date_string_col.to_timestamp(
"%m/%d/%y", 'non-utc-timezone'
)
).compile()


@pytest.mark.parametrize(
('date', 'expected_index', 'expected_day'),
[
Expand Down

0 comments on commit 169250f

Please sign in to comment.