@@ -517,35 +517,36 @@ protected virtual SqlExpression ConstructDate(IReadOnlyList<SqlExpression> argum
517517 /// <exception cref="InvalidOperationException"></exception>
518518 protected virtual SqlExpression ConstructTime ( IReadOnlyList < SqlExpression > arguments )
519519 {
520- SqlExpression hour , minute , second , millisecond ;
520+ SqlExpression hour , minute , second , microsecond ;
521521 if ( arguments . Count == 4 ) {
522522 hour = arguments [ 0 ] ;
523523 minute = arguments [ 1 ] ;
524524 second = arguments [ 2 ] ;
525- millisecond = arguments [ 3 ] ;
525+ microsecond = arguments [ 3 ] * 10000 ;
526526 }
527527 else if ( arguments . Count == 1 ) {
528528 var ticks = arguments [ 0 ] ;
529+ // try to optimize and reduce calculations when TimeSpan.Ticks where used for TimeOnly(ticks) ctor
530+ ticks = SqlHelper . IsTimeSpanTicks ( ticks , out var sourceInterval ) ? sourceInterval / 100 : ticks ;
529531 hour = SqlDml . Cast ( ticks / 36000000000 , SqlType . Int32 ) ;
530532 minute = SqlDml . Cast ( ( ticks / 600000000 ) % 60 , SqlType . Int32 ) ;
531533 second = SqlDml . Cast ( ( ticks / 10000000 ) % 60 , SqlType . Int32 ) ;
532- millisecond = SqlDml . Cast ( ticks % 10000000 , SqlType . Int32 ) ;
534+ microsecond = SqlDml . Cast ( ticks % 10000000 , SqlType . Int32 ) ;
533535 }
534536 else {
535537 throw new InvalidOperationException ( "Unsupported count of parameters" ) ;
536538 }
537539
538- return SqlDml . Cast (
539- DateAddMillisecond (
540- DateAddSecond (
541- DateAddMinute (
542- DateAddHour (
543- SqlDml . Literal ( new TimeOnly ( 0 , 0 , 0 ) ) ,
544- hour ) ,
545- minute ) ,
546- second ) ,
547- millisecond ) ,
548- SqlType . Time ) ;
540+ // Using string version of time allows to control hours overflow
541+ // we cannot add hours, minutes and other parts to 00:00:00.000000 time
542+ // because hours might step over 24 hours and start counting from 0.
543+ // Starting from v11 built-in function with hour overflow control is used.
544+ var hourString = SqlDml . Cast ( hour , new SqlValueType ( SqlType . VarChar , 3 ) ) ;
545+ var minuteString = SqlDml . Cast ( minute , new SqlValueType ( SqlType . VarChar , 2 ) ) ;
546+ var secondString = SqlDml . Cast ( second , new SqlValueType ( SqlType . VarChar , 2 ) ) ;
547+ var microsecondString = SqlDml . Cast ( microsecond , new SqlValueType ( SqlType . VarChar , 7 ) ) ;
548+ var composedTimeString = SqlDml . Concat ( hourString , SqlDml . Literal ( ":" ) , minuteString , SqlDml . Literal ( ":" ) , secondString , SqlDml . Literal ( "." ) , microsecondString ) ;
549+ return SqlDml . Cast ( composedTimeString , SqlType . Time ) ;
549550 }
550551
551552 /// <summary>
0 commit comments