зеркало из https://github.com/microsoft/Power-Fx.git
Support DateTimeFormat.UTC in Text (#1246)
Fix issue: https://github.com/microsoft/Power-Fx/issues/1240
This commit is contained in:
Родитель
3cddde71f3
Коммит
ffd33c7eb2
|
@ -47,7 +47,7 @@ namespace Microsoft.PowerFx.Functions
|
|||
private static readonly Regex _minutesDetokenizeRegex = new Regex("[\u000A][\u000A]+", RegExFlags);
|
||||
private static readonly Regex _secondsDetokenizeRegex = new Regex("[\u0008][\u0008]+", RegExFlags);
|
||||
private static readonly Regex _milisecondsDetokenizeRegex = new Regex("[\u000e]+", RegExFlags);
|
||||
|
||||
|
||||
// Char is used for PA string escaping
|
||||
public static FormulaValue Char(IRContext irContext, NumberValue[] args)
|
||||
{
|
||||
|
@ -264,7 +264,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);
|
||||
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "g", newDateTime.GetConvertedValue(timeZoneInfo), timeZoneInfo, culture, formatInfo.CancellationToken, out result);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -281,7 +281,7 @@ namespace Microsoft.PowerFx.Functions
|
|||
}
|
||||
else
|
||||
{
|
||||
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "g", dateTimeValue.GetConvertedValue(timeZoneInfo), culture, formatInfo.CancellationToken, out result);
|
||||
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "g", dateTimeValue.GetConvertedValue(timeZoneInfo), timeZoneInfo, culture, formatInfo.CancellationToken, out result);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -293,7 +293,7 @@ namespace Microsoft.PowerFx.Functions
|
|||
}
|
||||
else
|
||||
{
|
||||
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "d", dateValue.GetConvertedValue(timeZoneInfo), culture, formatInfo.CancellationToken, out result);
|
||||
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "d", dateValue.GetConvertedValue(timeZoneInfo), timeZoneInfo, culture, formatInfo.CancellationToken, out result);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -306,7 +306,7 @@ namespace Microsoft.PowerFx.Functions
|
|||
else
|
||||
{
|
||||
var dtValue = Library.TimeToDateTime(formatInfo, IRContext.NotInSource(FormulaType.DateTime), timeValue);
|
||||
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "t", dtValue.GetConvertedValue(timeZoneInfo), culture, formatInfo.CancellationToken, out result);
|
||||
return TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, formatString, "t", dtValue.GetConvertedValue(timeZoneInfo), timeZoneInfo, culture, formatInfo.CancellationToken, out result);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -321,14 +321,7 @@ namespace Microsoft.PowerFx.Functions
|
|||
return result != null;
|
||||
}
|
||||
|
||||
internal static FormulaValue ExpandDateTimeExcelFormatSpecifiers(IRContext irContext, string format, string defaultFormat, DateTime dateTime, CultureInfo culture, CancellationToken cancellationToken)
|
||||
{
|
||||
bool isStringValue = TryExpandDateTimeExcelFormatSpecifiersToStringValue(irContext, format, defaultFormat, dateTime, culture, cancellationToken, out StringValue result);
|
||||
|
||||
return isStringValue ? result : CommonErrors.GenericInvalidArgument(irContext, StringResources.Get(TexlStrings.ErrTextInvalidFormat, culture.Name));
|
||||
}
|
||||
|
||||
internal static bool TryExpandDateTimeExcelFormatSpecifiersToStringValue(IRContext irContext, string format, string defaultFormat, DateTime dateTime, CultureInfo culture, CancellationToken cancellationToken, out StringValue result)
|
||||
internal static bool TryExpandDateTimeExcelFormatSpecifiersToStringValue(IRContext irContext, string format, string defaultFormat, DateTime dateTime, TimeZoneInfo timeZoneInfo, CultureInfo culture, CancellationToken cancellationToken, out StringValue result)
|
||||
{
|
||||
result = null;
|
||||
if (format == null)
|
||||
|
@ -353,6 +346,11 @@ namespace Microsoft.PowerFx.Functions
|
|||
var formatStr = ExpandDateTimeFormatSpecifiers(format, culture);
|
||||
result = new StringValue(irContext, dateTime.ToString(formatStr, culture));
|
||||
break;
|
||||
case "'utc'":
|
||||
case "utc":
|
||||
var formatUtcStr = ExpandDateTimeFormatSpecifiers(format, culture);
|
||||
result = new StringValue(irContext, ConvertToUTC(dateTime, timeZoneInfo).ToString(formatUtcStr, culture));
|
||||
break;
|
||||
default:
|
||||
try
|
||||
{
|
||||
|
@ -399,7 +397,8 @@ namespace Microsoft.PowerFx.Functions
|
|||
case "'longdate'":
|
||||
return info.LongDatePattern;
|
||||
case "'utc'":
|
||||
return info.UniversalSortableDateTimePattern;
|
||||
case "utc":
|
||||
return "yyyy-MM-ddTHH:mm:ss.fffZ";
|
||||
default:
|
||||
return format;
|
||||
}
|
||||
|
@ -857,7 +856,7 @@ namespace Microsoft.PowerFx.Functions
|
|||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (--instanceNum == 0)
|
||||
{
|
||||
strBuilder.Replace(match.Value, replacement.Value, idx, match.Value.Length);
|
||||
|
@ -868,7 +867,7 @@ namespace Microsoft.PowerFx.Functions
|
|||
|
||||
return new StringValue(irContext, strBuilder.ToString());
|
||||
}
|
||||
|
||||
|
||||
public static FormulaValue StartsWith(IRContext irContext, StringValue[] args)
|
||||
{
|
||||
var text = args[0];
|
||||
|
@ -927,5 +926,11 @@ namespace Microsoft.PowerFx.Functions
|
|||
var logicalName = optionSet.Option;
|
||||
return new StringValue(irContext, logicalName);
|
||||
}
|
||||
|
||||
private static DateTime ConvertToUTC(DateTime dateTime, TimeZoneInfo fromTimeZone)
|
||||
{
|
||||
var resultDateTime = new DateTimeOffset(DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified), fromTimeZone.GetUtcOffset(dateTime));
|
||||
return resultDateTime.UtcDateTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,3 +44,6 @@ DateTime(2022,9,29,13,0,0,0)
|
|||
|
||||
>> DateTimeValue("2022-09-29T20:00:00-08:00")
|
||||
DateTime(2022,9,29,21,0,0,0)
|
||||
|
||||
>> Text(DateTime(2023, 3, 24, 19, 12, 34, 567), DateTimeFormat.UTC)
|
||||
"2023-03-25T02:12:34.567Z"
|
|
@ -99,3 +99,6 @@ DateTime(2011,1,30,8,0,0,0)
|
|||
|
||||
>> DateTimeValue("2011-01-30T08:00:00.1234567")
|
||||
DateTime(2011,1,30,8,0,0,123)
|
||||
|
||||
>> With({d:DateTimeValue("March 10, 2023 5:30 PM")}, DateTimeValue(Text(d, DateTimeFormat.UTC)) = d)
|
||||
true
|
|
@ -9,3 +9,6 @@ Date(2022,9,29)
|
|||
|
||||
>> DateValue("2022-09-29T20:00:00-08:00")
|
||||
Date(2022,9,30)
|
||||
|
||||
>> Text(DateTime(2023, 3, 24, 19, 12, 34, 567), DateTimeFormat.UTC)
|
||||
"2023-03-24T18:12:34.567Z"
|
|
@ -380,3 +380,9 @@ Error({Kind:ErrorKind.BadLanguageCode})
|
|||
//Excel doesn't support three arguments
|
||||
>> Text(Date(2016,1,31), "dddd mmmm d", "es-ES")
|
||||
"domingo enero 31"
|
||||
|
||||
>> Text(DateTimeValue("2023-02-03 04:05:06Z"), DateTimeFormat.UTC)
|
||||
"2023-02-03T04:05:06.000Z"
|
||||
|
||||
>> Text(DateTimeValue("2023-12-21T12:34:56.789Z"), DateTimeFormat.UTC)
|
||||
"2023-12-21T12:34:56.789Z"
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using Microsoft.PowerFx.Core.Tests;
|
||||
using Microsoft.PowerFx.Functions;
|
||||
using Microsoft.PowerFx.Syntax;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.PowerFx.Interpreter.Tests
|
||||
{
|
||||
public class TextDateTimeToUTCTests : PowerFxTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Text(DateTimeValue(\"March 10, 2023 5:30 PM\"), DateTimeFormat.UTC)", "Pacific Standard Time", "2023-03-11T01:30:00.000Z")]
|
||||
[InlineData("Text(DateTimeValue(\"March 10, 2023 5:30 PM\"), DateTimeFormat.UTC)", "Tokyo Standard Time", "2023-03-10T08:30:00.000Z")]
|
||||
[InlineData("Text(DateTimeValue(\"March 10, 2023 5:30 PM\"), DateTimeFormat.UTC)", "SE Asia Standard Time", "2023-03-10T10:30:00.000Z")]
|
||||
public async void TextDateTimeToUTC(string inputExp, string timeZoneId, string expectedDateTimeUTC)
|
||||
{
|
||||
var engine = new RecalcEngine();
|
||||
var rc = new RuntimeConfig();
|
||||
rc.SetTimeZone(TimeZoneInfo.FindSystemTimeZoneById(timeZoneId));
|
||||
|
||||
var check = engine.Check(inputExp);
|
||||
Assert.True(check.IsSuccess);
|
||||
|
||||
var utcResult = await check.GetEvaluator().EvalAsync(CancellationToken.None, rc);
|
||||
Assert.Equal(expectedDateTimeUTC, utcResult.ToObject());
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче