Out of range number to date returns an error (#1100)

Issue #1098 
Out of range number to date returns an error instead of throwing an
exception.
This commit is contained in:
Anderson Silva 2023-02-21 13:35:53 -06:00 коммит произвёл GitHub
Родитель 8071b3b3fc
Коммит 83e3f81772
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 40 добавлений и 8 удалений

Просмотреть файл

@ -556,6 +556,7 @@ namespace Microsoft.PowerFx.Core.Localization
public static ErrorResourceKey ErrTextTooLarge = new ErrorResourceKey("ErrTextTooLarge");
public static ErrorResourceKey ErrTextFormatTooLarge = new ErrorResourceKey("ErrTextFormatTooLarge");
public static ErrorResourceKey ErrTextInvalidFormat = new ErrorResourceKey("ErrTextInvalidFormat");
public static ErrorResourceKey ErrTextInvalidArgDateTime = new ErrorResourceKey("ErrTextInvalidArgDateTime");
public static ErrorResourceKey ErrBooleanExpected = new ErrorResourceKey("ErrBooleanExpected");
public static ErrorResourceKey ErrOnlyOneViewExpected = new ErrorResourceKey("ErrOnlyOneViewExpected");
public static ErrorResourceKey ErrViewFromCurrentTableExpected = new ErrorResourceKey("ErrViewFromCurrentTableExpected");

Просмотреть файл

@ -18,6 +18,7 @@ using Microsoft.PowerFx.Core.Types.Enums;
using Microsoft.PowerFx.Core.Utils;
using Microsoft.PowerFx.Interpreter;
using Microsoft.PowerFx.Types;
using static Microsoft.PowerFx.Core.Localization.TexlStrings;
namespace Microsoft.PowerFx.Functions
{
@ -259,6 +260,7 @@ namespace Microsoft.PowerFx.Functions
{
// It's a number, formatted as date/time. Let's convert it to a date/time value first
var newDateTime = Library.NumberToDateTime(formatInfo, IRContext.NotInSource(FormulaType.DateTime), num);
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "g", newDateTime.GetConvertedValue(timeZoneInfo), culture, formatInfo.CancellationToken, out result);
}
else

Просмотреть файл

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.PowerFx.Core.Errors;
using Microsoft.PowerFx.Core.IR;
using Microsoft.PowerFx.Core.IR.Nodes;
@ -432,12 +431,21 @@ namespace Microsoft.PowerFx.Functions
public static DateTimeValue NumberToDateTime(FormattingInfo formatInfo, IRContext irContext, NumberValue value)
{
var n = value.Value;
var date = _epoch.AddDays(n);
try
{
var n = value.Value;
var date = _epoch.AddDays(n);
date = MakeValidDateTime(formatInfo.TimeZoneInfo, date);
date = MakeValidDateTime(formatInfo.TimeZoneInfo, date);
return new DateTimeValue(irContext, date);
return new DateTimeValue(irContext, date);
}
catch (ArgumentOutOfRangeException)
{
(var shortMessage, _) = ErrorUtils.GetLocalizedErrorContent(TexlStrings.ErrTextInvalidArgDateTime, formatInfo.CultureInfo, out _);
throw new CustomFunctionErrorException(shortMessage, ErrorKind.InvalidArgument);
}
}
public static FormulaValue DateToDateTime(EvalVisitor runner, EvalVisitorContext context, IRContext irContext, FormulaValue[] args)

Просмотреть файл

@ -1849,6 +1849,10 @@
<value>Invalid format.</value>
<comment>Error Message returned by the Text function when the format passed to it is invalid.</comment>
</data>
<data name="ErrTextInvalidArgDateTime" xml:space="preserve">
<value>The argument does not represent a valid date or time value.</value>
<comment>Error Message returned by the Text function when the number to date format exceeds the max days to add.</comment>
</data>
<data name="ErrInvalidDataSource" xml:space="preserve">
<value>This Data source is invalid. Please fix the error in "Data sources" pane by clicking "Content -&gt; Data sources" or "View -&gt; Options"</value>
<comment>Error Message.</comment>

Просмотреть файл

@ -636,6 +636,10 @@ Error({Kind:ErrorKind.InvalidArgument})
>> Text(30470.01953125, "YYYY-MM-DD HH:MM:SS.00000000")
Error({Kind:ErrorKind.InvalidArgument})
// Number 4492800 exceeds the max days that DateTime.AddDays can take.
>> Text(4492800,DateTimeFormat.LongDate)
Error({Kind:ErrorKind.InvalidArgument})
// C# interpreter can handle up to 7 decimals after the second
>> Text(DateTimeValue("2023-01-03 00:01:02.3456789"), "yyyy-mm-dd hh:mm:ss.0000000")
"2023-01-03 00:01:02.3456789"

Просмотреть файл

@ -2,8 +2,10 @@
// Licensed under the MIT license.
using System;
using System.Numerics;
using Microsoft.PowerFx;
using Microsoft.PowerFx.Core.Tests;
using Microsoft.PowerFx.Interpreter;
using Microsoft.PowerFx.Types;
using Xunit;
@ -53,6 +55,17 @@ namespace Microsoft.PowerFx.Tests
TryCoerceToTargetTypes(FormulaValue.New(DateTime.Parse(value)), exprBool, exprNumber, exprStr, exprDateTime);
}
// From number to datetime, expects an exception
[Theory]
[InlineData(4496200)]
[InlineData(4E8)]
public void TryCoerceFromNumberExpectsExceptionTest(double value)
{
var inputValue = FormulaValue.New(value);
Assert.Throws<CustomFunctionErrorException>(() => inputValue.TryCoerceTo(out DateTimeValue resultDateTime));
}
private void TryCoerceToTargetTypes(FormulaValue inputValue, string exprBool, string exprNumber, string exprStr, string exprDateTime)
{
bool isSucceeded = inputValue.TryCoerceTo(out BooleanValue resultBoolean);
@ -79,16 +92,16 @@ namespace Microsoft.PowerFx.Tests
Assert.Null(resultNumber);
}
isSucceeded = inputValue.TryCoerceTo(out StringValue resultString);
isSucceeded = inputValue.TryCoerceTo(out StringValue resultValue);
if (exprStr != null)
{
Assert.True(isSucceeded);
Assert.Equal(exprStr, resultString.Value);
Assert.Equal(exprStr, resultValue.Value);
}
else
{
Assert.False(isSucceeded);
Assert.Null(resultString);
Assert.IsType<ErrorValue>(resultValue);
}
isSucceeded = inputValue.TryCoerceTo(out DateTimeValue resultDateTime);