diff --git a/samples/OracleProvider/test/OracleProvider.FunctionalTests/Query/DbFunctionsOracleTest.cs b/samples/OracleProvider/test/OracleProvider.FunctionalTests/Query/DbFunctionsOracleTest.cs index 2ec87cf96b2..739bf92f7a4 100644 --- a/samples/OracleProvider/test/OracleProvider.FunctionalTests/Query/DbFunctionsOracleTest.cs +++ b/samples/OracleProvider/test/OracleProvider.FunctionalTests/Query/DbFunctionsOracleTest.cs @@ -27,23 +27,5 @@ public override void String_Like_Literal() Assert.Equal(19, count); // TODO: case-sensitive - use REGEXP_LIKE function? } } - - [ConditionalFact(Skip = "See issue#10520")] - public override void DateDiff_Microsecond() - { - base.DateDiff_Microsecond(); - } - - [ConditionalFact(Skip = "See issue#10520")] - public override void DateDiff_Millisecond() - { - base.DateDiff_Millisecond(); - } - - [ConditionalFact(Skip = "See issue#10520")] - public override void DateDiff_Nanosecond() - { - base.DateDiff_Nanosecond(); - } } } diff --git a/src/EFCore.Specification.Tests/Query/DbFunctionsTestBase.cs b/src/EFCore.Specification.Tests/Query/DbFunctionsTestBase.cs index 82f74685f61..82beada069f 100644 --- a/src/EFCore.Specification.Tests/Query/DbFunctionsTestBase.cs +++ b/src/EFCore.Specification.Tests/Query/DbFunctionsTestBase.cs @@ -51,114 +51,6 @@ public virtual void String_Like_Literal_With_Escape() } } - [ConditionalFact] - public virtual void DateDiff_Year() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffYear(c.OrderDate, DateTime.Now) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Month() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffMonth(c.OrderDate, DateTime.Now) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Day() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffDay(c.OrderDate, DateTime.Now) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Hour() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffHour(c.OrderDate, DateTime.Now) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Minute() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffMinute(c.OrderDate, DateTime.Now) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Second() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffSecond(c.OrderDate, DateTime.Now) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Millisecond() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffMillisecond(DateTime.Now, DateTime.Now.AddDays(1)) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Microsecond() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffMicrosecond(DateTime.Now, DateTime.Now.AddSeconds(1)) == 0); - - Assert.Equal(0, count); - } - } - - [ConditionalFact] - public virtual void DateDiff_Nanosecond() - { - using (var context = CreateContext()) - { - var count = context.Orders - .Count(c => EF.Functions.DateDiffNanosecond(DateTime.Now, DateTime.Now.AddSeconds(1)) == 0); - - Assert.Equal(0, count); - } - } - protected NorthwindContext CreateContext() => Fixture.CreateContext(); } } diff --git a/src/EFCore.SqlServer/Query/ExpressionTranslators/Internal/SqlServerDateDiffTranslator.cs b/src/EFCore.SqlServer/Query/ExpressionTranslators/Internal/SqlServerDateDiffTranslator.cs index 7b24b423ae7..0b41e6e425a 100644 --- a/src/EFCore.SqlServer/Query/ExpressionTranslators/Internal/SqlServerDateDiffTranslator.cs +++ b/src/EFCore.SqlServer/Query/ExpressionTranslators/Internal/SqlServerDateDiffTranslator.cs @@ -20,218 +20,218 @@ private readonly Dictionary _methodInfoDateDiffMapping = new Dictionary { { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffYear), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "YEAR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffYear), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "YEAR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffYear), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "YEAR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffYear), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffYear), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "YEAR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMonth), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "MONTH" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMonth), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "MONTH" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMonth), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "MONTH" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMonth), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMonth), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "MONTH" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffDay), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "DAY" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffDay), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "DAY" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffDay), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "DAY" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffDay), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffDay), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "DAY" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffHour), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "HOUR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffHour), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "HOUR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffHour), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "HOUR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffHour), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffHour), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "HOUR" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMinute), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "MINUTE" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMinute), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "MINUTE" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMinute), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "MINUTE" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMinute), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMinute), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "MINUTE" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffSecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "SECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffSecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "SECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffSecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "SECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffSecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffSecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "SECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMillisecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "MILLISECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMillisecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "MILLISECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMillisecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "MILLISECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMillisecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMillisecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "MILLISECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMicrosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "MICROSECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMicrosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "MICROSECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMicrosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "MICROSECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMicrosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffMicrosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "MICROSECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffNanosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }), "NANOSECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffNanosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }), "NANOSECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffNanosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset), typeof(DateTimeOffset) }), "NANOSECOND" }, { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffNanosecond), + typeof(SqlServerDbFunctionsExtensions).GetRuntimeMethod( + nameof(SqlServerDbFunctionsExtensions.DateDiffNanosecond), new[] { typeof(DbFunctions), typeof(DateTimeOffset?), typeof(DateTimeOffset?) }), "NANOSECOND" } diff --git a/src/EFCore.SqlServer/SqlServerDbFunctionsExtensions.cs b/src/EFCore.SqlServer/SqlServerDbFunctionsExtensions.cs index 47c6698a7c9..ddc0fdf196d 100644 --- a/src/EFCore.SqlServer/SqlServerDbFunctionsExtensions.cs +++ b/src/EFCore.SqlServer/SqlServerDbFunctionsExtensions.cs @@ -55,5 +55,575 @@ private static bool FreeTextCore(string propertyName, string freeText, int? lang { throw new InvalidOperationException(SqlServerStrings.FreeTextFunctionOnClient); } + + /// + /// Counts the number of year boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of year boundaries crossed between the dates. + public static int DateDiffYear( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + => endDate.Year - startDate.Year; + + /// + /// Counts the number of year boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of year boundaries crossed between the dates. + public static int? DateDiffYear( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffYear(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of year boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of year boundaries crossed between the dates. + public static int DateDiffYear( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffYear(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of year boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of year boundaries crossed between the dates. + public static int? DateDiffYear( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffYear(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of month boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of month boundaries crossed between the dates. + public static int DateDiffMonth( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + => 12 * (endDate.Year - startDate.Year) + endDate.Month - startDate.Month; + + /// + /// Counts the number of month boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of month boundaries crossed between the dates. + public static int? DateDiffMonth( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMonth(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of month boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of month boundaries crossed between the dates. + public static int DateDiffMonth( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffMonth(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of month boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of month boundaries crossed between the dates. + public static int? DateDiffMonth( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMonth(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of day boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of day boundaries crossed between the dates. + public static int DateDiffDay( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + => (endDate.Date - startDate.Date).Days; + + /// + /// Counts the number of day boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of day boundaries crossed between the dates. + public static int? DateDiffDay( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffDay(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of day boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of day boundaries crossed between the dates. + public static int DateDiffDay( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffDay(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of day boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of day boundaries crossed between the dates. + public static int? DateDiffDay( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffDay(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of hour boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of hour boundaries crossed between the dates. + public static int DateDiffHour( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + { + checked + { + return DateDiffDay(_, startDate, endDate) * 24 + endDate.Hour - startDate.Hour; + } + } + + /// + /// Counts the number of hour boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of hour boundaries crossed between the dates. + public static int? DateDiffHour( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffHour(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of hour boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of hour boundaries crossed between the dates. + public static int DateDiffHour( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffHour(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of hour boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of hour boundaries crossed between the dates. + public static int? DateDiffHour( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffHour(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of minute boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of minute boundaries crossed between the dates. + public static int DateDiffMinute( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + { + checked + { + return DateDiffHour(_, startDate, endDate) * 60 + endDate.Minute - startDate.Minute; + } + } + + /// + /// Counts the number of minute boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of minute boundaries crossed between the dates. + public static int? DateDiffMinute( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMinute(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of minute boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of minute boundaries crossed between the dates. + public static int DateDiffMinute( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffMinute(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of minute boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of minute boundaries crossed between the dates. + public static int? DateDiffMinute( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMinute(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of second boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of second boundaries crossed between the dates. + public static int DateDiffSecond( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + { + checked + { + return DateDiffMinute(_, startDate, endDate) * 60 + endDate.Second - startDate.Second; + } + } + + /// + /// Counts the number of second boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of second boundaries crossed between the dates. + public static int? DateDiffSecond( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffSecond(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of second boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of second boundaries crossed between the dates. + public static int DateDiffSecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffSecond(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of second boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of second boundaries crossed between the dates. + public static int? DateDiffSecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffSecond(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of millisecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of millisecond boundaries crossed between the dates. + public static int DateDiffMillisecond( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + { + checked + { + return DateDiffSecond(_, startDate, endDate) * 1000 + endDate.Millisecond - startDate.Millisecond; + } + } + + /// + /// Counts the number of millisecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of millisecond boundaries crossed between the dates. + public static int? DateDiffMillisecond( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMillisecond(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of millisecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of millisecond boundaries crossed between the dates. + public static int DateDiffMillisecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffMillisecond(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of millisecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of millisecond boundaries crossed between the dates. + public static int? DateDiffMillisecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMillisecond(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of microsecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of microsecond boundaries crossed between the dates. + public static int DateDiffMicrosecond( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + { + checked + { + return (int)((endDate.Ticks - startDate.Ticks) / 10); + } + } + + /// + /// Counts the number of microsecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of microsecond boundaries crossed between the dates. + public static int? DateDiffMicrosecond( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMicrosecond(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of microsecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of microsecond boundaries crossed between the dates. + public static int DateDiffMicrosecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffMicrosecond(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of microsecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of microsecond boundaries crossed between the dates. + public static int? DateDiffMicrosecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffMicrosecond(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of nanosecond boundaries crossed between the dates. + public static int DateDiffNanosecond( + [CanBeNull] this DbFunctions _, + DateTime startDate, + DateTime endDate) + { + checked + { + return (int)((endDate.Ticks - startDate.Ticks) * 100); + } + } + + /// + /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of nanosecond boundaries crossed between the dates. + public static int? DateDiffNanosecond( + [CanBeNull] this DbFunctions _, + DateTime? startDate, + DateTime? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffNanosecond(_, startDate.Value, endDate.Value) + : null; + + /// + /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of nanosecond boundaries crossed between the dates. + public static int DateDiffNanosecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset startDate, + DateTimeOffset endDate) + => DateDiffNanosecond(_, startDate.UtcDateTime, endDate.UtcDateTime); + + /// + /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. + /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). + /// + /// The DbFunctions instance. + /// Starting date for the calculation. + /// Ending date for the calculation. + /// Number of nanosecond boundaries crossed between the dates. + public static int? DateDiffNanosecond( + [CanBeNull] this DbFunctions _, + DateTimeOffset? startDate, + DateTimeOffset? endDate) + => (startDate.HasValue && endDate.HasValue) + ? (int?)DateDiffNanosecond(_, startDate.Value, endDate.Value) + : null; } } diff --git a/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteCompositeMethodCallTranslator.cs b/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteCompositeMethodCallTranslator.cs index 7e33a6c43fe..7875a85abbf 100644 --- a/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteCompositeMethodCallTranslator.cs +++ b/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteCompositeMethodCallTranslator.cs @@ -14,7 +14,6 @@ public class SqliteCompositeMethodCallTranslator : RelationalCompositeMethodCall private static readonly IMethodCallTranslator[] _sqliteTranslators = { new SqliteContainsOptimizedTranslator(), - new SqliteDateDiffTranslator(), new SqliteEndsWithOptimizedTranslator(), new SqliteMathTranslator(), new SqliteStartsWithOptimizedTranslator(), diff --git a/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteDateDiffTranslator.cs b/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteDateDiffTranslator.cs deleted file mode 100644 index d14875e3882..00000000000 --- a/src/EFCore.Sqlite.Core/Query/ExpressionTranslators/Internal/SqliteDateDiffTranslator.cs +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Reflection; -using System.Collections.Generic; -using System.Linq.Expressions; -using Microsoft.EntityFrameworkCore.Query.Expressions; -using Microsoft.EntityFrameworkCore.Utilities; - -namespace Microsoft.EntityFrameworkCore.Query.ExpressionTranslators.Internal -{ - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public class SqliteDateDiffTranslator : IMethodCallTranslator - { - private static readonly List _dateDiffMethodInfos - = new List - { - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffYear), - new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffYear), - new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMonth), - new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMonth), - new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffDay), - new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffDay), - new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffHour), - new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffHour), - new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMinute), - new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffMinute), - new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffSecond), - new[] { typeof(DbFunctions), typeof(DateTime), typeof(DateTime) }) - }, - { - typeof(DbFunctionsExtensions).GetRuntimeMethod( - nameof(DbFunctionsExtensions.DateDiffSecond), - new[] { typeof(DbFunctions), typeof(DateTime?), typeof(DateTime?) }) - } - }; - - private static readonly Dictionary _datePartMapping - = new Dictionary - { - { nameof(DateTime.Year), "'%Y'" }, - { nameof(DateTime.Month), "'%m'" }, - { nameof(DateTime.Hour), "'%H'" }, - { nameof(DateTime.Minute), "'%M'" }, - { nameof(DateTime.Second), "'%S'" }, - }; - - /// - /// This API supports the Entity Framework Core infrastructure and is not intended to be used - /// directly from your code. This API may change or be removed in future releases. - /// - public virtual Expression Translate(MethodCallExpression methodCallExpression) - { - Check.NotNull(methodCallExpression, nameof(methodCallExpression)); - - if (_dateDiffMethodInfos.Contains(methodCallExpression.Method)) - { - var endDate = methodCallExpression.Arguments[2]; - var startDate = methodCallExpression.Arguments[1]; - - switch (methodCallExpression.Method.Name) - { - case nameof(DbFunctionsExtensions.DateDiffYear): - return DateDiffYear(startDate, endDate); - - case nameof(DbFunctionsExtensions.DateDiffMonth): - return DateDiffMonth(startDate, endDate); - - case nameof(DbFunctionsExtensions.DateDiffDay): - return DateDiffDay(startDate, endDate); - - case nameof(DbFunctionsExtensions.DateDiffHour): - return DateDiffHour(startDate, endDate); - - case nameof(DbFunctionsExtensions.DateDiffMinute): - return DateDiffMinute(startDate, endDate); - - case nameof(DbFunctionsExtensions.DateDiffSecond): - return DateDiffSecond(startDate, endDate); - } - } - - return null; - } - - private Expression DateDiffYear(Expression startDate, Expression endDate) - { - return Expression.Subtract( - GetDatePart(endDate, nameof(DateTime.Year)), - GetDatePart(startDate, nameof(DateTime.Year))); - } - - private Expression DateDiffMonth(Expression startDate, Expression endDate) - { - return Expression.Add( - Expression.Multiply( - Expression.Constant(12, typeof(int?)), - DateDiffYear(startDate, endDate)), - Expression.Subtract( - GetDatePart(endDate, nameof(DateTime.Month)), - GetDatePart(startDate, nameof(DateTime.Month)))); - } - - private Expression DateDiffDay(Expression startDate, Expression endDate) - { - return Expression.Subtract(GetJulianDay(endDate), GetJulianDay(startDate)); - } - - private Expression DateDiffHour(Expression startDate, Expression endDate) - { - return Expression.Add( - Expression.Multiply( - Expression.Constant(24, typeof(int?)), - DateDiffDay(startDate, endDate)), - Expression.Subtract( - GetDatePart(endDate, nameof(DateTime.Hour)), - GetDatePart(startDate, nameof(DateTime.Hour)))); - } - - private Expression DateDiffMinute(Expression startDate, Expression endDate) - { - return Expression.Add( - Expression.Multiply( - Expression.Constant(60, typeof(int?)), - DateDiffHour(startDate, endDate)), - Expression.Subtract( - GetDatePart(endDate, nameof(DateTime.Minute)), - GetDatePart(startDate, nameof(DateTime.Minute)))); - } - - private Expression DateDiffSecond(Expression startDate, Expression endDate) - { - return Expression.Add( - Expression.Multiply( - Expression.Constant(60, typeof(int?)), - DateDiffMinute(startDate, endDate)), - Expression.Subtract( - GetDatePart(endDate, nameof(DateTime.Second)), - GetDatePart(startDate, nameof(DateTime.Second)))); - } - - private SqlFunctionExpression GetJulianDay(Expression date) - { - return new SqlFunctionExpression( - "julianday", - typeof(int?), - new Expression[] - { - date, - new SqlFragmentExpression("'start of day'") - }); - } - - private ExplicitCastExpression GetDatePart(Expression date, string memberName) - { - return new ExplicitCastExpression( - new SqlFunctionExpression( - "strftime", - date.Type, - new[] { - new SqlFragmentExpression(_datePartMapping[memberName]), - date - }), - typeof(int?)); - } - } -} diff --git a/src/EFCore/DbFunctionsExtensions.cs b/src/EFCore/DbFunctionsExtensions.cs index 86d2a133e67..b9a73293a1e 100644 --- a/src/EFCore/DbFunctionsExtensions.cs +++ b/src/EFCore/DbFunctionsExtensions.cs @@ -17,576 +17,6 @@ namespace Microsoft.EntityFrameworkCore // ReSharper disable once InconsistentNaming public static class DbFunctionsExtensions { - /// - /// Counts the number of year boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of year boundaries crossed between the dates. - public static int DateDiffYear( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - => endDate.Year - startDate.Year; - - /// - /// Counts the number of year boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of year boundaries crossed between the dates. - public static int? DateDiffYear( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffYear(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of year boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of year boundaries crossed between the dates. - public static int DateDiffYear( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffYear(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of year boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(YEAR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of year boundaries crossed between the dates. - public static int? DateDiffYear( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffYear(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of month boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of month boundaries crossed between the dates. - public static int DateDiffMonth( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - => 12 * (endDate.Year - startDate.Year) + endDate.Month - startDate.Month; - - /// - /// Counts the number of month boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of month boundaries crossed between the dates. - public static int? DateDiffMonth( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMonth(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of month boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of month boundaries crossed between the dates. - public static int DateDiffMonth( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffMonth(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of month boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MONTH,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of month boundaries crossed between the dates. - public static int? DateDiffMonth( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMonth(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of day boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of day boundaries crossed between the dates. - public static int DateDiffDay( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - => (endDate.Date - startDate.Date).Days; - - /// - /// Counts the number of day boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of day boundaries crossed between the dates. - public static int? DateDiffDay( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffDay(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of day boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of day boundaries crossed between the dates. - public static int DateDiffDay( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffDay(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of day boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(DAY,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of day boundaries crossed between the dates. - public static int? DateDiffDay( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffDay(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of hour boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of hour boundaries crossed between the dates. - public static int DateDiffHour( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - { - checked - { - return DateDiffDay(_, startDate, endDate) * 24 + endDate.Hour - startDate.Hour; - } - } - - /// - /// Counts the number of hour boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of hour boundaries crossed between the dates. - public static int? DateDiffHour( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffHour(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of hour boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of hour boundaries crossed between the dates. - public static int DateDiffHour( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffHour(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of hour boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(HOUR,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of hour boundaries crossed between the dates. - public static int? DateDiffHour( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffHour(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of minute boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of minute boundaries crossed between the dates. - public static int DateDiffMinute( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - { - checked - { - return DateDiffHour(_, startDate, endDate) * 60 + endDate.Minute - startDate.Minute; - } - } - - /// - /// Counts the number of minute boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of minute boundaries crossed between the dates. - public static int? DateDiffMinute( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMinute(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of minute boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of minute boundaries crossed between the dates. - public static int DateDiffMinute( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffMinute(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of minute boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MINUTE,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of minute boundaries crossed between the dates. - public static int? DateDiffMinute( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMinute(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of second boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of second boundaries crossed between the dates. - public static int DateDiffSecond( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - { - checked - { - return DateDiffMinute(_, startDate, endDate) * 60 + endDate.Second - startDate.Second; - } - } - - /// - /// Counts the number of second boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of second boundaries crossed between the dates. - public static int? DateDiffSecond( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffSecond(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of second boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of second boundaries crossed between the dates. - public static int DateDiffSecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffSecond(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of second boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(SECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of second boundaries crossed between the dates. - public static int? DateDiffSecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffSecond(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of millisecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of millisecond boundaries crossed between the dates. - public static int DateDiffMillisecond( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - { - checked - { - return DateDiffSecond(_, startDate, endDate) * 1000 + endDate.Millisecond - startDate.Millisecond; - } - } - - /// - /// Counts the number of millisecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of millisecond boundaries crossed between the dates. - public static int? DateDiffMillisecond( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMillisecond(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of millisecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of millisecond boundaries crossed between the dates. - public static int DateDiffMillisecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffMillisecond(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of millisecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MILLISECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of millisecond boundaries crossed between the dates. - public static int? DateDiffMillisecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMillisecond(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of microsecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of microsecond boundaries crossed between the dates. - public static int DateDiffMicrosecond( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - { - checked - { - return (int)((endDate.Ticks - startDate.Ticks) / 10); - } - } - - /// - /// Counts the number of microsecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of microsecond boundaries crossed between the dates. - public static int? DateDiffMicrosecond( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMicrosecond(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of microsecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of microsecond boundaries crossed between the dates. - public static int DateDiffMicrosecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffMicrosecond(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of microsecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(MICROSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of microsecond boundaries crossed between the dates. - public static int? DateDiffMicrosecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffMicrosecond(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of nanosecond boundaries crossed between the dates. - public static int DateDiffNanosecond( - [CanBeNull] this DbFunctions _, - DateTime startDate, - DateTime endDate) - { - checked - { - return (int)((endDate.Ticks - startDate.Ticks) * 100); - } - } - - /// - /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of nanosecond boundaries crossed between the dates. - public static int? DateDiffNanosecond( - [CanBeNull] this DbFunctions _, - DateTime? startDate, - DateTime? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffNanosecond(_, startDate.Value, endDate.Value) - : null; - - /// - /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of nanosecond boundaries crossed between the dates. - public static int DateDiffNanosecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset startDate, - DateTimeOffset endDate) - => DateDiffNanosecond(_, startDate.UtcDateTime, endDate.UtcDateTime); - - /// - /// Counts the number of nanosecond boundaries crossed between the startDate and endDate. - /// Corresponds to SQL Server's DATEDIFF(NANOSECOND,startDate,endDate). - /// - /// The DbFunctions instance. - /// Starting date for the calculation. - /// Ending date for the calculation. - /// Number of nanosecond boundaries crossed between the dates. - public static int? DateDiffNanosecond( - [CanBeNull] this DbFunctions _, - DateTimeOffset? startDate, - DateTimeOffset? endDate) - => (startDate.HasValue && endDate.HasValue) - ? (int?)DateDiffNanosecond(_, startDate.Value, endDate.Value) - : null; - /// /// /// An implementation of the SQL LIKE operation. On relational databases this is usually directly diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/DbFunctionsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/DbFunctionsSqlServerTest.cs index dd1264151d1..d058a5213df 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/DbFunctionsSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/DbFunctionsSqlServerTest.cs @@ -225,97 +225,152 @@ await Assert.ThrowsAsync( e => EF.Functions.FreeText(e.City, e.FirstName.ToUpper()))); } } -#endif - public override void DateDiff_Year() + [ConditionalFact] + public virtual void DateDiff_Year() { - base.DateDiff_Year(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffYear(c.OrderDate, DateTime.Now) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(YEAR, [c].[OrderDate], GETDATE()) = 0"); + } } - public override void DateDiff_Month() + [ConditionalFact] + public virtual void DateDiff_Month() { - base.DateDiff_Month(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffMonth(c.OrderDate, DateTime.Now) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(MONTH, [c].[OrderDate], GETDATE()) = 0"); + } } - public override void DateDiff_Day() + [ConditionalFact] + public virtual void DateDiff_Day() { - base.DateDiff_Day(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffDay(c.OrderDate, DateTime.Now) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(DAY, [c].[OrderDate], GETDATE()) = 0"); + } } - public override void DateDiff_Hour() + [ConditionalFact] + public virtual void DateDiff_Hour() { - base.DateDiff_Hour(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffHour(c.OrderDate, DateTime.Now) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(HOUR, [c].[OrderDate], GETDATE()) = 0"); + } } - public override void DateDiff_Minute() + [ConditionalFact] + public virtual void DateDiff_Minute() { - base.DateDiff_Minute(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffMinute(c.OrderDate, DateTime.Now) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(MINUTE, [c].[OrderDate], GETDATE()) = 0"); + } } - public override void DateDiff_Second() + [ConditionalFact] + public virtual void DateDiff_Second() { - base.DateDiff_Second(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffSecond(c.OrderDate, DateTime.Now) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(SECOND, [c].[OrderDate], GETDATE()) = 0"); + } } - public override void DateDiff_Millisecond() + [ConditionalFact] + public virtual void DateDiff_Millisecond() { - base.DateDiff_Millisecond(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffMillisecond(DateTime.Now, DateTime.Now.AddDays(1)) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(MILLISECOND, GETDATE(), DATEADD(day, 1E0, GETDATE())) = 0"); + } } - public override void DateDiff_Microsecond() + [ConditionalFact] + public virtual void DateDiff_Microsecond() { - base.DateDiff_Microsecond(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffMicrosecond(DateTime.Now, DateTime.Now.AddSeconds(1)) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(MICROSECOND, GETDATE(), DATEADD(second, 1E0, GETDATE())) = 0"); + } } - public override void DateDiff_Nanosecond() + [ConditionalFact] + public virtual void DateDiff_Nanosecond() { - base.DateDiff_Nanosecond(); + using (var context = CreateContext()) + { + var count = context.Orders + .Count(c => EF.Functions.DateDiffNanosecond(DateTime.Now, DateTime.Now.AddSeconds(1)) == 0); - AssertSql( - @"SELECT COUNT(*) + Assert.Equal(0, count); + AssertSql( + @"SELECT COUNT(*) FROM [Orders] AS [c] WHERE DATEDIFF(NANOSECOND, GETDATE(), DATEADD(second, 1E0, GETDATE())) = 0"); + } } +#endif private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/DbFunctionsSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/DbFunctionsSqliteTest.cs index d380c6ae868..4e724bd8809 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/DbFunctionsSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/DbFunctionsSqliteTest.cs @@ -11,74 +11,7 @@ public class DbFunctionsSqliteTest : DbFunctionsTestBase fixture, ITestOutputHelper testOutputHelper) : base(fixture) { - fixture.TestSqlLoggerFactory.Clear(); + Fixture.TestSqlLoggerFactory.Clear(); } - - public override void DateDiff_Year() - { - base.DateDiff_Year(); - - AssertSql( - @"SELECT COUNT(*) -FROM ""Orders"" AS ""c"" -WHERE (CAST(strftime('%Y', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%Y', ""c"".""OrderDate"") AS INTEGER)) = 0"); - } - - public override void DateDiff_Month() - { - base.DateDiff_Month(); - - AssertSql( - @"SELECT COUNT(*) -FROM ""Orders"" AS ""c"" -WHERE ((12 * (CAST(strftime('%Y', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%Y', ""c"".""OrderDate"") AS INTEGER))) + (CAST(strftime('%m', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%m', ""c"".""OrderDate"") AS INTEGER))) = 0"); - - } - - public override void DateDiff_Day() - { - base.DateDiff_Day(); - - AssertSql( - @"SELECT COUNT(*) -FROM ""Orders"" AS ""c"" -WHERE (julianday(rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.'), 'start of day') - julianday(""c"".""OrderDate"", 'start of day')) = 0"); - - } - - public override void DateDiff_Hour() - { - base.DateDiff_Hour(); - - AssertSql( - @"SELECT COUNT(*) -FROM ""Orders"" AS ""c"" -WHERE ((24 * (julianday(rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.'), 'start of day') - julianday(""c"".""OrderDate"", 'start of day'))) + (CAST(strftime('%H', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%H', ""c"".""OrderDate"") AS INTEGER))) = 0"); - - } - - public override void DateDiff_Minute() - { - base.DateDiff_Minute(); - - AssertSql( - @"SELECT COUNT(*) -FROM ""Orders"" AS ""c"" -WHERE ((60 * ((24 * (julianday(rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.'), 'start of day') - julianday(""c"".""OrderDate"", 'start of day'))) + (CAST(strftime('%H', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%H', ""c"".""OrderDate"") AS INTEGER)))) + (CAST(strftime('%M', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%M', ""c"".""OrderDate"") AS INTEGER))) = 0"); - } - - public override void DateDiff_Second() - { - base.DateDiff_Second(); - - AssertSql( - @"SELECT COUNT(*) -FROM ""Orders"" AS ""c"" -WHERE ((60 * ((60 * ((24 * (julianday(rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.'), 'start of day') - julianday(""c"".""OrderDate"", 'start of day'))) + (CAST(strftime('%H', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%H', ""c"".""OrderDate"") AS INTEGER)))) + (CAST(strftime('%M', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%M', ""c"".""OrderDate"") AS INTEGER)))) + (CAST(strftime('%S', rtrim(rtrim(strftime('%Y-%m-%d %H:%M:%f', 'now', 'localtime'), '0'), '.')) AS INTEGER) - CAST(strftime('%S', ""c"".""OrderDate"") AS INTEGER))) = 0"); - - } - - private void AssertSql(params string[] expected) - => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } }