[PT Run > Time and Date plugin] Custom formats and other improvements (#37743)

* add settings definition

* fix typos and improve settings

* make spell checker happy

* new icon type error

* first code to handle custom formats

* support parsing of new formats

* spelling and typos

* comment fix

* spell check

* start implement custom format results

* last changes

* finish implementation

* spell checker

* settings name

* add missing format

* reorder settings

* dev docs

* change ELF to EAB

* update dev docs

* last changes

* test cases

* fix typos

* fix typo

* port changes

* fixes

* changes

* fixes

* leap year support

* days in month

* tests

* comment

* fix comment
This commit is contained in:
Heiko
2025-04-01 15:31:35 +02:00
committed by GitHub
parent 721c84d3a6
commit ce620e427f
14 changed files with 892 additions and 94 deletions

View File

@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.PowerToys.Run.Plugin.TimeDate.Components;
@@ -23,7 +24,7 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
var result = settings?.Length;
// Assert
Assert.AreEqual(6, result);
Assert.AreEqual(7, result);
}
[DataTestMethod]
@@ -33,6 +34,7 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
[DataRow("TimeWithSeconds")]
[DataRow("DateWithWeekday")]
[DataRow("HideNumberMessageOnGlobalQuery")]
[DataRow("CustomFormats")]
public void DoesSettingExist(string name)
{
// Setup
@@ -78,5 +80,20 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
// Assert
Assert.AreEqual(valueExpected, result);
}
[DataTestMethod]
[DataRow("CustomFormats")]
public void DefaultEmptyMultilineTextValues(string name)
{
// Setup
TimeDateSettings setting = TimeDateSettings.Instance;
// Act
PropertyInfo propertyInfo = setting?.GetType()?.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Instance);
List<string> result = (List<string>)propertyInfo?.GetValue(setting);
// Assert
Assert.AreEqual(0, result.Count);
}
}
}

View File

@@ -54,11 +54,11 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
[DataTestMethod]
[DataRow("(time", 18)]
[DataRow("(date", 26)]
[DataRow("(year", 7)]
[DataRow("(now", 32)]
[DataRow("(current", 32)]
[DataRow("(", 32)]
[DataRow("(date", 28)]
[DataRow("(year", 8)]
[DataRow("(now", 34)]
[DataRow("(current", 34)]
[DataRow("(", 34)]
[DataRow("(now::10:10:10", 1)] // Windows file time
[DataRow("(current::10:10:10", 0)]
public void CountWithPluginKeyword(string typedString, int expectedResultCount)
@@ -140,6 +140,8 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
[DataRow("(week day", "Day of the week (Week day) -")]
[DataRow("(cal week", "Week of the year (Calendar week, Week number) -")]
[DataRow("(week num", "Week of the year (Calendar week, Week number) -")]
[DataRow("(days in mo", "Days in month -")]
[DataRow("(Leap y", "Leap year -")]
public void CanFindFormatResult(string typedString, string expectedResult)
{
// Setup

View File

@@ -41,10 +41,29 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
[DataRow("ums-10456", true, "", "")] // Value is UTC and can be different based on system
[DataRow("ums+10456", true, "", "")] // Value is UTC and can be different based on system
[DataRow("ft10456", true, "", "")] // Value is UTC and can be different based on system
[DataRow("oa-657434.99999999", true, "G", "1/1/0100 11:59:59 PM")]
[DataRow("oa2958465.99999999", true, "G", "12/31/9999 11:59:59 PM")]
[DataRow("oa-657435", false, "", "")] // Value to low
[DataRow("oa2958466", false, "", "")] // Value to large
[DataRow("exc1.99998843", true, "G", "1/1/1900 11:59:59 PM")]
[DataRow("exc59.99998843", true, "G", "2/28/1900 11:59:59 PM")]
[DataRow("exc61", true, "G", "3/1/1900 12:00:00 AM")]
[DataRow("exc62.99998843", true, "G", "3/2/1900 11:59:59 PM")]
[DataRow("exc2958465.99998843", true, "G", "12/31/9999 11:59:59 PM")]
[DataRow("exc0", false, "", "")] // Day 0 means in Excel 0/1/1900 and this is a fake date.
[DataRow("exc0.99998843", false, "", "")] // Day 0 means in Excel 0/1/1900 and this is a fake date.
[DataRow("exc60.99998843", false, "", "")] // Day 60 means in Excel 2/29/1900 and this is a fake date in Excel which we cannot support.
[DataRow("exc60", false, "", "")] // Day 60 means in Excel 2/29/1900 and this is a fake date in Excel which we cannot support.
[DataRow("exc-1", false, "", "")] // Value to low
[DataRow("exc2958466", false, "", "")] // Value to large
[DataRow("exf0.99998843", true, "G", "1/1/1904 11:59:59 PM")]
[DataRow("exf2957003.99998843", true, "G", "12/31/9999 11:59:59 PM")]
[DataRow("exf-0.5", false, "", "")] // Value to low
[DataRow("exf2957004", false, "", "")] // Value to large
public void ConvertStringToDateTime(string typedString, bool expectedBool, string stringType, string expectedString)
{
// Act
bool boolResult = TimeAndDateHelper.ParseStringAsDateTime(in typedString, out DateTime result);
bool boolResult = TimeAndDateHelper.ParseStringAsDateTime(in typedString, out DateTime result, out string _);
// Assert
Assert.AreEqual(expectedBool, boolResult);

View File

@@ -13,6 +13,19 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
[TestClass]
public class TimeAndDateHelperTests
{
private CultureInfo originalCulture;
private CultureInfo originalUiCulture;
[TestInitialize]
public void Setup()
{
// Set culture to 'en-us'
originalCulture = CultureInfo.CurrentCulture;
CultureInfo.CurrentCulture = new CultureInfo("en-us", false);
originalUiCulture = CultureInfo.CurrentUICulture;
CultureInfo.CurrentUICulture = new CultureInfo("en-us", false);
}
[DataTestMethod]
[DataRow(-1, null)] // default setting
[DataRow(0, CalendarWeekRule.FirstDay)]
@@ -62,5 +75,103 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests
Assert.AreEqual(valueExpected, result);
}
}
[DataTestMethod]
[DataRow(0, "12/30/1899 12:00 PM", 0.5)] // OLE Automation date
[DataRow(1, "12/31/1898 12:00 PM", null)] // Excel based 1900: Date to low
[DataRow(1, "1/1/1900, 00:00 AM", 1.0)] // Excel based 1900
[DataRow(2, "12/31/1898 12:00 PM", null)] // Excel based 1904: Date to low
[DataRow(2, "1/1/1904, 00:00 AM", 0.0)] // Excel based 1904
public void ConvertToOADateFormat(int type, string date, double? valueExpected)
{
// Act
DateTime dt = DateTime.Parse(date, DateTimeFormatInfo.CurrentInfo);
// Assert
if (valueExpected == null)
{
Assert.ThrowsException<ArgumentOutOfRangeException>(() => TimeAndDateHelper.ConvertToOleAutomationFormat(dt, (OADateFormats)type));
}
else
{
var result = TimeAndDateHelper.ConvertToOleAutomationFormat(dt, (OADateFormats)type);
Assert.AreEqual(valueExpected, result);
}
}
[DataTestMethod]
[DataRow("dow")]
[DataRow("\\DOW")]
[DataRow("wom")]
[DataRow("\\WOM")]
[DataRow("woy")]
[DataRow("\\WOY")]
[DataRow("eab")]
[DataRow("\\EAB")]
[DataRow("wft")]
[DataRow("\\WFT")]
[DataRow("uxt")]
[DataRow("\\UXT")]
[DataRow("ums")]
[DataRow("\\UMS")]
[DataRow("oad")]
[DataRow("\\OAD")]
[DataRow("exc")]
[DataRow("\\EXC")]
[DataRow("exf")]
[DataRow("\\EXF")]
[DataRow("My super Test String with \\EXC pattern.")]
public void CustomFormatIgnoreInvalidPattern(string format)
{
// Act
string result = TimeAndDateHelper.ConvertToCustomFormat(DateTime.Now, 0, 0, 1, "AD", format, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
// Assert
Assert.AreEqual(format, result);
}
[DataTestMethod]
[DataRow("DOW")]
[DataRow("DIM")]
[DataRow("WOM")]
[DataRow("WOY")]
[DataRow("EAB")]
[DataRow("WFT")]
[DataRow("UXT")]
[DataRow("UMS")]
[DataRow("OAD")]
[DataRow("EXC")]
[DataRow("EXF")]
public void CustomFormatReplacesValidPattern(string format)
{
// Act
string result = TimeAndDateHelper.ConvertToCustomFormat(DateTime.Now, 0, 0, 1, "AD", format, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
// Assert
Assert.IsFalse(result.Contains(format, StringComparison.CurrentCulture));
}
[DataTestMethod]
[DataRow("01/01/0001", 1)] // First possible date
[DataRow("12/31/9999", 5)] // Last possible date
[DataRow("03/20/2025", 4)]
[DataRow("09/01/2025", 1)] // First day in month is first day of week
[DataRow("03/03/2025", 2)] // First monday is in second week
public void GetWeekOfMonth(string date, int week)
{
// Act
int result = TimeAndDateHelper.GetWeekOfMonth(DateTime.Parse(date, CultureInfo.GetCultureInfo("en-us")), DayOfWeek.Monday);
// Assert
Assert.AreEqual(result, week);
}
[TestCleanup]
public void CleanUp()
{
// Set culture to original value
CultureInfo.CurrentCulture = originalCulture;
CultureInfo.CurrentUICulture = originalUiCulture;
}
}
}