Not a viable solution in a production environment, but you could increment the date until you hit the out-of-bounds error and catch the result:
BEGIN TRY
DECLARE
@Step_Cnt INT = 0
, @Ms_Increment int = 0
, @StartDate datetime = '9999-12-31T23:59:59.900'
, @CurDate datetime
, @MaxTries int = 10000;
set @CurDate = @StartDate
WHILE TRY_CONVERT( datetime, @CurDate ) is not null and @Step_Cnt < @MaxTries
BEGIN
/* handle variable accuracy "Rounded to increments of .000, .003, or .007 seconds" */
set @Ms_Increment = 0
WHILE dateadd( millisecond, @Ms_Increment, @CurDate ) = @CurDate
BEGIN
SET @Ms_Increment = @Ms_Increment + 1;
SET @CurDate = dateadd( millisecond, @Ms_Increment, @CurDate )
END;
set @Step_Cnt = @Step_Cnt + 1
END;
select 'OK' as [Status],@StartDate as [StartDate], @Step_Cnt as [NumSteps], @CurDate as [FinalDate]
END TRY
BEGIN CATCH
select 'Caught' as [Status],@StartDate as [StartDate], @Step_Cnt as [NumSteps], @CurDate as [FinalDate]
END CATCH;