Skip to content

Commit

Permalink
Add DateTimeOffset.ToUnixTimeSeconds() and DateTimeOffset.ToUnixTimeM…
Browse files Browse the repository at this point in the history
…illiseconds() support.
  • Loading branch information
lauxjpn committed Sep 29, 2023
1 parent 9560947 commit b78b8c0
Showing 1 changed file with 42 additions and 4 deletions.
46 changes: 42 additions & 4 deletions src/EFCore.MySql/Query/Internal/MySqlDateTimeMethodTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,27 @@ public class MySqlDateTimeMethodTranslator : IMethodCallTranslator
{ typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddHours), new[] { typeof(double) }), "hour" },
{ typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMinutes), new[] { typeof(double) }), "minute" },
{ typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddSeconds), new[] { typeof(double) }), "second" },
{ typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }), "microsecond" },
{ typeof(DateTime).GetRuntimeMethod(nameof(DateTime.AddMilliseconds), new[] { typeof(double) }), "millisecond" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddYears), new[] { typeof(int) }), "year" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMonths), new[] { typeof(int) }), "month" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddDays), new[] { typeof(double) }), "day" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddHours), new[] { typeof(double) }), "hour" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMinutes), new[] { typeof(double) }), "minute" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddSeconds), new[] { typeof(double) }), "second" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMilliseconds), new[] { typeof(double) }), "microsecond" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.AddMilliseconds), new[] { typeof(double) }), "millisecond" },
{ typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddYears), new[] { typeof(int) }), "year" },
{ typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddMonths), new[] { typeof(int) }), "month" },
{ typeof(DateOnly).GetRuntimeMethod(nameof(DateOnly.AddDays), new[] { typeof(int) }), "day" },
{ typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.AddHours), new[] { typeof(double) }), "hour" },
{ typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.AddMinutes), new[] { typeof(double) }), "minute" },
};

private static readonly Dictionary<MethodInfo, string> _methodInfoDateDiffMapping = new()
{
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.ToUnixTimeSeconds), Type.EmptyTypes)!, "second" },
{ typeof(DateTimeOffset).GetRuntimeMethod(nameof(DateTimeOffset.ToUnixTimeMilliseconds), Type.EmptyTypes)!, "millisecond" }
};

private static readonly MethodInfo _timeOnlyAddTimeSpanMethod = typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.Add), new[] { typeof(TimeSpan) })!;
private static readonly MethodInfo _timeOnlyIsBetweenMethod = typeof(TimeOnly).GetRuntimeMethod(nameof(TimeOnly.IsBetween), new[] { typeof(TimeOnly), typeof(TimeOnly) })!;

Expand Down Expand Up @@ -70,12 +76,15 @@ public virtual SqlExpression Translate(
new SqlExpression[]
{
_sqlExpressionFactory.Fragment("INTERVAL"),
datePart.Equals("microsecond")
datePart.Equals("millisecond")
? _sqlExpressionFactory.Multiply(
_sqlExpressionFactory.Constant(1000),
_sqlExpressionFactory.Convert(arguments[0], typeof(int)))
: _sqlExpressionFactory.Convert(arguments[0], typeof(int)),
_sqlExpressionFactory.Fragment(datePart)
_sqlExpressionFactory.Fragment(
datePart == "millisecond"
? "microsecond"
: datePart)
},
" ",
typeof(string))
Expand All @@ -86,6 +95,35 @@ public virtual SqlExpression Translate(
new[] {true, false});
}

if (method.DeclaringType == typeof(DateTimeOffset) &&
instance is not null)
{
if (_methodInfoDateDiffMapping.TryGetValue(method, out var timePart))
{
SqlExpression expression = _sqlExpressionFactory.NullableFunction(
"TIMESTAMPDIFF",
new[]
{
_sqlExpressionFactory.Fragment(timePart == "millisecond" ? "microsecond" : timePart),
_sqlExpressionFactory.Constant(DateTimeOffset.UnixEpoch, instance!.TypeMapping),
instance
},
typeof(long),
typeMapping: null,
onlyNullWhenAnyNullPropagatingArgumentIsNull: true,
argumentsPropagateNullability: new[] { false, true, true });

if (timePart == "millisecond")
{
expression = _sqlExpressionFactory.MySqlIntegerDivide(
expression,
_sqlExpressionFactory.Constant(1_000));
}

return expression;
}
}

if (method.DeclaringType == typeof(TimeOnly))
{
if (method == _timeOnlyAddTimeSpanMethod)
Expand Down

0 comments on commit b78b8c0

Please sign in to comment.