mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
[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:
8
.github/actions/spell-check/expect.txt
vendored
8
.github/actions/spell-check/expect.txt
vendored
@@ -15,6 +15,7 @@ ACTIVATEAPP
|
||||
activationaction
|
||||
ACVS
|
||||
adaptivecards
|
||||
ADate
|
||||
ADDSTRING
|
||||
ADDUNDORECORD
|
||||
ADifferent
|
||||
@@ -417,6 +418,7 @@ DWORDLONG
|
||||
dworigin
|
||||
dwrite
|
||||
dxgi
|
||||
eab
|
||||
easeofaccess
|
||||
ecount
|
||||
Edid
|
||||
@@ -466,6 +468,7 @@ EXAND
|
||||
EXCLUDEFROMCAPTURE
|
||||
executionpolicy
|
||||
exename
|
||||
exf
|
||||
EXITSIZEMOVE
|
||||
exlist
|
||||
EXPCMDFLAGS
|
||||
@@ -898,6 +901,7 @@ MARKDOWNPREVIEWHANDLERCPP
|
||||
MAXIMIZEBOX
|
||||
MAXSHORTCUTSIZE
|
||||
maxversiontested
|
||||
mber
|
||||
MBM
|
||||
MBR
|
||||
MDICHILD
|
||||
@@ -1779,6 +1783,8 @@ USRDLL
|
||||
UType
|
||||
uuidv
|
||||
uwp
|
||||
ums
|
||||
uxt
|
||||
uxtheme
|
||||
vabdq
|
||||
validmodulename
|
||||
@@ -1859,6 +1865,7 @@ webbrowsers
|
||||
webpage
|
||||
websites
|
||||
wekyb
|
||||
wft
|
||||
wgpocpl
|
||||
WHEREID
|
||||
Wholegrain
|
||||
@@ -1919,6 +1926,7 @@ WNDCLASSEXW
|
||||
WNDCLASSW
|
||||
WNDPROC
|
||||
wnode
|
||||
wom
|
||||
WORKSPACESEDITOR
|
||||
WORKSPACESLAUNCHER
|
||||
WORKSPACESSNAPSHOTTOOL
|
||||
|
||||
@@ -16,49 +16,70 @@ The 'Time and Date' plugin shows the date and time in different formats. For the
|
||||
### Available formats
|
||||
|
||||
**Remarks**
|
||||
- The following formats requires a prefix in the query:
|
||||
- The following formats requires a prefix in the query when using them as date input:
|
||||
- Unix Timestamp: `u`
|
||||
- Unix Timestamp in milliseconds: `ums`
|
||||
- Windows file time: `ft`
|
||||
- OLE Automation date: `oa`
|
||||
- Excel 1900 date value: `exc`
|
||||
- Excel 1904 date value: `exf`
|
||||
- On invalid number inputs we show a warning that tells the user which prefixes are allowed/required.
|
||||
|
||||
**List of available formats**
|
||||
|
||||
The following formats are currently available:
|
||||
|
||||
| Format | Example (Based on default settings) | As result | As input |
|
||||
| Format | Example (Based on default settings) | As result | As input | Result as custom format only
|
||||
|--------------|-----------|------------|------------|
|
||||
| Time | 5:10 PM | x | x |
|
||||
| Date | 3/5/2022 | x | x |
|
||||
| Now | 3/5/2022 5:10 PM | x | x |
|
||||
| Time UTC | 4:10 PM | x | x |
|
||||
| Now UTC | 3/5/2022 4:10 PM | x | x |
|
||||
| Unix Timestamp | 1646496622 | x | x |
|
||||
| Unix Timestamp in milliseconds | 1646496622500 | x | x |
|
||||
| Hour | 10 | x | |
|
||||
| Minute | 30 | x | |
|
||||
| Second | 45 | x | |
|
||||
| Millisecond | 678 | x | |
|
||||
| Day (Week day) | Saturday | x | |
|
||||
| Day of the week | 6 | x | |
|
||||
| Day of the month | 5 | x | |
|
||||
| Day of the year | 64 | x | |
|
||||
| Week of the month | 1 | x | |
|
||||
| Week of the year (Calendar week, Week number) | 10 | x | |
|
||||
| Month | March | x | |
|
||||
| Month of the year | 3 | x | |
|
||||
| Month and day | March 7 | x | x |
|
||||
| Year | 2022 | x | |
|
||||
| Era | AD | x | |
|
||||
| Era abbreviation | A | x | |
|
||||
| Month and year | March 2022 | x | x |
|
||||
| Windows file time (Int64 number) | 637820976123938199 | x | x |
|
||||
| Universal time format: YYYY-MM-DD hh:mm:ss| 2022-03-05 16:20:12Z | x | x |
|
||||
| ISO 8601 | 2022-03-05T17:23:04 | x | x |
|
||||
| ISO 8601 UTC | 2022-03-05T16:23:04 | x | x |
|
||||
| ISO 8601 with time zone | 2022-03-05T17:23:04+01:00 | x | x |
|
||||
| ISO 8601 UTC with time zone | 2022-03-05T16:23:04Z | x | x |
|
||||
| RFC1123 | Sat, 05 Mar 2022 16:23:04 GMT | x | x |
|
||||
| Time | 5:10 PM | x | x | |
|
||||
| Date | 3/5/2022 | x | x | |
|
||||
| Now | 3/5/2022 5:10 PM | x | x | |
|
||||
| Time UTC | 4:10 PM | x | x | |
|
||||
| Now UTC | 3/5/2022 4:10 PM | x | x | |
|
||||
| Unix Timestamp | 1646496622 | x | x | |
|
||||
| Unix Timestamp in milliseconds | 1646496622500 | x | x | |
|
||||
| Hour | 10 | x | | |
|
||||
| Minute | 30 | x | | |
|
||||
| Second | 45 | x | | |
|
||||
| Millisecond | 678 | x | | |
|
||||
| Day (Week day) | Saturday | x | | |
|
||||
| Day of the week | 6 | x | | |
|
||||
| Day of the month | 5 | x | | |
|
||||
| Day of the year | 64 | x | | |
|
||||
| Week of the month | 1 | x | | |
|
||||
| Week of the year (Calendar week, Week number) | 10 | x | | |
|
||||
| Month | March | x | | |
|
||||
| Month of the year | 3 | x | | |
|
||||
| Month and day | March 7 | x | x | |
|
||||
| Year | 2022 | x | | |
|
||||
| Era | AD | x | | |
|
||||
| Era abbreviation | A | x | | |
|
||||
| Month and year | March 2022 | x | x | |
|
||||
| Windows file time (Int64 number) | 637820976123938199 | x | x | |
|
||||
| Universal time format: YYYY-MM-DD hh:mm:ss| 2022-03-05 16:20:12Z | x | x | |
|
||||
| ISO 8601 | 2022-03-05T17:23:04 | x | x | |
|
||||
| ISO 8601 UTC | 2022-03-05T16:23:04 | x | x | |
|
||||
| ISO 8601 with time zone | 2022-03-05T17:23:04+01:00 | x | x | |
|
||||
| ISO 8601 UTC with time zone | 2022-03-05T16:23:04Z | x | x | |
|
||||
| RFC1123 | Sat, 05 Mar 2022 16:23:04 GMT | x | x | |
|
||||
| OLE Automation date | 45723.44143763889 | | x | x |
|
||||
| Excel's 1900 date value | 45723.44143763889 | | x | x |
|
||||
| Excel's 1904 date value | 44261.44143763889 | | x | x |
|
||||
|
||||
**Custom format definition**
|
||||
The user can create its own formats. One per line in the settings text box. The format of each line is `<name>=<syntax pattern>`.
|
||||
If the syntax pattern starting with `UTC:` then we use the UTC time instead of the local time.
|
||||
As syntax pattern the pattern from `DateTime.ToString()` and the following custom pattern are available:
|
||||
- DOW: Number of the day in the week.
|
||||
- WOM: Number of week in the month.
|
||||
- WOY: Number of the week in the year.
|
||||
- EAB: Era abbreviation.
|
||||
- WFT: Windows file time.
|
||||
- UXT: Unix time stamp.
|
||||
- UMS: Unix time stamp in milliseconds.
|
||||
- OAD: OLE Automation date.
|
||||
- EXC: Excel's 1900 based date value.
|
||||
- EXF: Excel's 1904 based date value.
|
||||
|
||||
### Add new formats
|
||||
- To add a new formats you have to add them to the method `GetList()` of the [`AvailableResultsList`](/src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/AvailableResultsList.cs) class.
|
||||
@@ -73,13 +94,13 @@ The following formats are currently available:
|
||||
|
||||
| Key | Type | Default value | Name | Description |
|
||||
|--------------|--------------|-----------|------------|------------|
|
||||
| `CalendarFirstWeekRule` | Combo box | `-1` (Use system settings) | First week of the year | Configure the calendar rule for the first week of the year. |
|
||||
| `FirstDayOfWeek` | Combo box | `-1` (Use system settings) | First day of the week | |
|
||||
| `OnlyDateTimeNowGlobal` | Checkbox | `true` | Show only 'Time', 'Date', and 'Now' result for system time on global queries | Regardless of this setting, for global queries the first word of the query has to be a complete match. |
|
||||
| `TimeWithSeconds` | Checkbox | `false` | Show time with seconds | This setting applies to the 'Time' and 'Now' result. |
|
||||
| `DateWithWeekday` | Checkbox | `false` | Show date with weekday and name of month | This setting applies to the 'Date' and 'Now' result. |
|
||||
| `HideNumberMessageOnGlobalQuery` | Checkbox | `false` | Hide 'Invalid number input' error message on global queries | |
|
||||
|
||||
| `CalendarFirstWeekRule` | Combo box | `-1` (Use system settings) | First week of the year | Configure the calendar rule for the first week of the year. |
|
||||
| `FirstDayOfWeek` | Combo box | `-1` (Use system settings) | First day of the week | |
|
||||
| `CustomFormats` | Multiline text box | `string.Empty` | Custom formats | Use date and time string format syntax and DOW (Day of Week), WOM (Week of Month), WOY (Week of the year), EAB (Era abbreviation), WFT (Windows File Time), UXT (Unix Time), UMS (Unix Time in milliseconds), OAD (OLE Automation date), EXC (Excel's 1900 based date value), EXF (Excel's 1904 based date value). If the format starts with UTC:, then Universal Time (UTC) is used. (Use a backslash to escape format sequences and the backslash character as text.) |
|
||||
|
||||
## Classes
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
{
|
||||
internal class AvailableResult
|
||||
internal sealed class AvailableResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the time/date value
|
||||
@@ -41,6 +41,7 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
ResultIconType.Time => $"Images\\time.{theme}.png",
|
||||
ResultIconType.Date => $"Images\\calendar.{theme}.png",
|
||||
ResultIconType.DateTime => $"Images\\timeDate.{theme}.png",
|
||||
ResultIconType.Error => $"Images\\Warning.{theme}.png",
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
@@ -51,5 +52,6 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
Time,
|
||||
Date,
|
||||
DateTime,
|
||||
Error,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.PowerToys.Run.Plugin.TimeDate.Properties;
|
||||
|
||||
namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
@@ -72,6 +72,86 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
string era = DateTimeFormatInfo.CurrentInfo.GetEraName(calendar.GetEra(dateTimeNow));
|
||||
string eraShort = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedEraName(calendar.GetEra(dateTimeNow));
|
||||
|
||||
// Custom formats
|
||||
foreach (string f in TimeDateSettings.Instance.CustomFormats)
|
||||
{
|
||||
string[] formatParts = f.Split("=", 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
string formatSyntax = formatParts.Length == 2 ? formatParts[1] : string.Empty;
|
||||
string searchTags = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagCustom");
|
||||
DateTime dtObject = dateTimeNow;
|
||||
|
||||
// If Length = 0 then empty string.
|
||||
if (formatParts.Length >= 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Verify and check input and update search tags
|
||||
if (formatParts.Length == 1)
|
||||
{
|
||||
throw new FormatException("Format syntax part after equal sign is missing.");
|
||||
}
|
||||
|
||||
bool containsCustomSyntax = TimeAndDateHelper.StringContainsCustomFormatSyntax(formatSyntax);
|
||||
if (formatSyntax.StartsWith("UTC:", StringComparison.InvariantCulture))
|
||||
{
|
||||
searchTags = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagCustomUtc");
|
||||
dtObject = dateTimeNowUtc;
|
||||
}
|
||||
|
||||
// Get formated date
|
||||
var value = TimeAndDateHelper.ConvertToCustomFormat(dtObject, unixTimestamp, unixTimestampMilliseconds, weekOfYear, eraShort, Regex.Replace(formatSyntax, "^UTC:", string.Empty), firstWeekRule, firstDayOfTheWeek);
|
||||
try
|
||||
{
|
||||
value = dtObject.ToString(value, CultureInfo.CurrentCulture);
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (!containsCustomSyntax)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not fail as we have custom format syntax. Instead fix backslashes.
|
||||
value = Regex.Replace(value, @"(?<!\\)\\", string.Empty).Replace("\\\\", "\\");
|
||||
}
|
||||
}
|
||||
|
||||
// Add result
|
||||
results.Add(new AvailableResult()
|
||||
{
|
||||
Value = value,
|
||||
Label = formatParts[0],
|
||||
AlternativeSearchTag = searchTags,
|
||||
IconType = ResultIconType.DateTime,
|
||||
});
|
||||
}
|
||||
catch (ArgumentOutOfRangeException e)
|
||||
{
|
||||
Wox.Plugin.Logger.Log.Exception($"Failed to convert into custom format {formatParts[0]}: {formatSyntax}", e, typeof(AvailableResultsList));
|
||||
results.Add(new AvailableResult()
|
||||
{
|
||||
Value = Resources.Microsoft_plugin_timedate_ErrorConvertCustomFormat + " " + e.Message,
|
||||
Label = formatParts[0],
|
||||
AlternativeSearchTag = searchTags,
|
||||
IconType = ResultIconType.Error,
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Wox.Plugin.Logger.Log.Exception($"Failed to convert into custom format {formatParts[0]}: {formatSyntax}", e, typeof(AvailableResultsList));
|
||||
results.Add(new AvailableResult()
|
||||
{
|
||||
Value = Resources.Microsoft_plugin_timedate_InvalidCustomFormat + " " + formatSyntax,
|
||||
Label = formatParts[0],
|
||||
AlternativeSearchTag = searchTags,
|
||||
IconType = ResultIconType.Error,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Predefined formats
|
||||
results.AddRange(new[]
|
||||
{
|
||||
new AvailableResult()
|
||||
@@ -152,6 +232,13 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
IconType = ResultIconType.Date,
|
||||
},
|
||||
new AvailableResult()
|
||||
{
|
||||
Value = DateTime.DaysInMonth(dateTimeNow.Year, dateTimeNow.Month).ToString(CultureInfo.CurrentCulture),
|
||||
Label = Resources.Microsoft_plugin_timedate_DaysInMonth,
|
||||
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
|
||||
IconType = ResultIconType.Date,
|
||||
},
|
||||
new AvailableResult()
|
||||
{
|
||||
Value = dateTimeNow.DayOfYear.ToString(CultureInfo.CurrentCulture),
|
||||
Label = Resources.Microsoft_plugin_timedate_DayOfYear,
|
||||
@@ -201,6 +288,13 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
IconType = ResultIconType.Date,
|
||||
},
|
||||
new AvailableResult()
|
||||
{
|
||||
Value = DateTime.IsLeapYear(dateTimeNow.Year) ? Resources.Microsoft_plugin_timedate_LeapYear : Resources.Microsoft_plugin_timedate_NoLeapYear,
|
||||
Label = Resources.Microsoft_plugin_timedate_LeapYear,
|
||||
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
|
||||
IconType = ResultIconType.Date,
|
||||
},
|
||||
new AvailableResult()
|
||||
{
|
||||
Value = era,
|
||||
Label = Resources.Microsoft_plugin_timedate_Era,
|
||||
@@ -221,13 +315,31 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
|
||||
IconType = ResultIconType.Date,
|
||||
},
|
||||
new AvailableResult()
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
results.Add(new AvailableResult()
|
||||
{
|
||||
Value = dateTimeNow.ToFileTime().ToString(CultureInfo.CurrentCulture),
|
||||
Label = Resources.Microsoft_plugin_timedate_WindowsFileTime,
|
||||
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
|
||||
IconType = ResultIconType.DateTime,
|
||||
},
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
results.Add(new AvailableResult()
|
||||
{
|
||||
Value = Resources.Microsoft_plugin_timedate_ErrorConvertWft,
|
||||
Label = Resources.Microsoft_plugin_timedate_WindowsFileTime,
|
||||
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
|
||||
IconType = ResultIconType.Error,
|
||||
});
|
||||
}
|
||||
|
||||
results.AddRange(new[]
|
||||
{
|
||||
new AvailableResult()
|
||||
{
|
||||
Value = dateTimeNowUtc.ToString("u"),
|
||||
|
||||
@@ -83,10 +83,10 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
/// Gets a result with an error message that only numbers can't be parsed
|
||||
/// </summary>
|
||||
/// <returns>Element of type <see cref="Result"/>.</returns>
|
||||
internal static Result CreateNumberErrorResult(string theme) => new Result()
|
||||
internal static Result CreateNumberErrorResult(string theme, string title, string subtitle) => new Result()
|
||||
{
|
||||
Title = Resources.Microsoft_plugin_timedate_ErrorResultTitle,
|
||||
SubTitle = Resources.Microsoft_plugin_timedate_ErrorResultSubTitle,
|
||||
Title = title,
|
||||
SubTitle = subtitle,
|
||||
ToolTipData = new ToolTipData(Resources.Microsoft_plugin_timedate_ErrorResultTitle, Resources.Microsoft_plugin_timedate_ErrorResultSubTitle),
|
||||
IcoPath = $"Images\\Warning.{theme}.png",
|
||||
};
|
||||
|
||||
@@ -40,9 +40,12 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
List<AvailableResult> availableFormats = new List<AvailableResult>();
|
||||
List<Result> results = new List<Result>();
|
||||
bool isKeywordSearch = !string.IsNullOrEmpty(query.ActionKeyword);
|
||||
bool isEmptySearchInput = string.IsNullOrEmpty(query.Search);
|
||||
bool isEmptySearchInput = string.IsNullOrWhiteSpace(query.Search);
|
||||
string searchTerm = query.Search;
|
||||
|
||||
// Last input parsing error
|
||||
string lastInputParsingErrorReason = string.Empty;
|
||||
|
||||
// Conjunction search without keyword => return no results
|
||||
// (This improves the results on global queries.)
|
||||
if (!isKeywordSearch && _conjunctionList.Any(x => x.Equals(searchTerm, StringComparison.CurrentCultureIgnoreCase)))
|
||||
@@ -61,13 +64,13 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
{
|
||||
// Search for specified format with specified time/date value
|
||||
var userInput = searchTerm.Split(InputDelimiter);
|
||||
if (TimeAndDateHelper.ParseStringAsDateTime(userInput[1], out DateTime timestamp))
|
||||
if (TimeAndDateHelper.ParseStringAsDateTime(userInput[1], out DateTime timestamp, out lastInputParsingErrorReason))
|
||||
{
|
||||
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, null, null, timestamp));
|
||||
searchTerm = userInput[0];
|
||||
}
|
||||
}
|
||||
else if (TimeAndDateHelper.ParseStringAsDateTime(searchTerm, out DateTime timestamp))
|
||||
else if (TimeAndDateHelper.ParseStringAsDateTime(searchTerm, out DateTime timestamp, out lastInputParsingErrorReason))
|
||||
{
|
||||
// Return all formats for specified time/date value
|
||||
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, null, null, timestamp));
|
||||
@@ -122,12 +125,15 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
}
|
||||
|
||||
// If search term is only a number that can't be parsed return an error message
|
||||
if (!isEmptySearchInput && results.Count == 0 && Regex.IsMatch(searchTerm, @"\w+\d+.*$") && !searchTerm.Any(char.IsWhiteSpace) && (TimeAndDateHelper.IsSpecialInputParsing(searchTerm) || !Regex.IsMatch(searchTerm, @"\d+[\.:/]\d+")))
|
||||
if (!isEmptySearchInput && results.Count == 0 && Regex.IsMatch(searchTerm, @"\w+[+-]?\d+.*$") && !searchTerm.Any(char.IsWhiteSpace) && (TimeAndDateHelper.IsSpecialInputParsing(searchTerm) || !Regex.IsMatch(searchTerm, @"\d+[\.:/]\d+")))
|
||||
{
|
||||
// Without plugin key word show only if message is not hidden by setting
|
||||
string title = !string.IsNullOrEmpty(lastInputParsingErrorReason) ? Resources.Microsoft_plugin_timedate_ErrorResultValue : Resources.Microsoft_plugin_timedate_ErrorResultTitle;
|
||||
string message = !string.IsNullOrEmpty(lastInputParsingErrorReason) ? lastInputParsingErrorReason : Resources.Microsoft_plugin_timedate_ErrorResultSubTitle;
|
||||
|
||||
// Without plugin key word show only if not hidden by setting
|
||||
if (isKeywordSearch || !TimeDateSettings.Instance.HideNumberMessageOnGlobalQuery)
|
||||
{
|
||||
results.Add(ResultHelper.CreateNumberErrorResult(iconTheme));
|
||||
results.Add(ResultHelper.CreateNumberErrorResult(iconTheme, title, message));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.PowerToys.Run.Plugin.TimeDate.Properties;
|
||||
|
||||
[assembly: InternalsVisibleTo("Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests")]
|
||||
|
||||
@@ -13,6 +15,33 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
{
|
||||
internal static class TimeAndDateHelper
|
||||
{
|
||||
private static readonly Regex _regexSpecialInputFormats = new Regex(@"^.*(::)?(u|ums|ft|oa|exc|exf)[+-]\d");
|
||||
private static readonly Regex _regexCustomDateTimeFormats = new Regex(@"(?<!\\)(DOW|DIM|WOM|WOY|EAB|WFT|UXT|UMS|OAD|EXC|EXF)");
|
||||
private static readonly Regex _regexCustomDateTimeDow = new Regex(@"(?<!\\)DOW");
|
||||
private static readonly Regex _regexCustomDateTimeDim = new Regex(@"(?<!\\)DIM");
|
||||
private static readonly Regex _regexCustomDateTimeWom = new Regex(@"(?<!\\)WOM");
|
||||
private static readonly Regex _regexCustomDateTimeWoy = new Regex(@"(?<!\\)WOY");
|
||||
private static readonly Regex _regexCustomDateTimeEab = new Regex(@"(?<!\\)EAB");
|
||||
private static readonly Regex _regexCustomDateTimeWft = new Regex(@"(?<!\\)WFT");
|
||||
private static readonly Regex _regexCustomDateTimeUxt = new Regex(@"(?<!\\)UXT");
|
||||
private static readonly Regex _regexCustomDateTimeUms = new Regex(@"(?<!\\)UMS");
|
||||
private static readonly Regex _regexCustomDateTimeOad = new Regex(@"(?<!\\)OAD");
|
||||
private static readonly Regex _regexCustomDateTimeExc = new Regex(@"(?<!\\)EXC");
|
||||
private static readonly Regex _regexCustomDateTimeExf = new Regex(@"(?<!\\)EXF");
|
||||
|
||||
private const long UnixTimeSecondsMin = -62135596800;
|
||||
private const long UnixTimeSecondsMax = 253402300799;
|
||||
private const long UnixTimeMillisecondsMin = -62135596800000;
|
||||
private const long UnixTimeMillisecondsMax = 253402300799999;
|
||||
private const long WindowsFileTimeMin = 0;
|
||||
private const long WindowsFileTimeMax = 2650467707991000000;
|
||||
private const double OADateMin = -657434.99999999;
|
||||
private const double OADateMax = 2958465.99999999;
|
||||
private const double Excel1900DateMin = 1;
|
||||
private const double Excel1900DateMax = 2958465.99998843;
|
||||
private const double Excel1904DateMin = 0;
|
||||
private const double Excel1904DateMax = 2957003.99998843;
|
||||
|
||||
/// <summary>
|
||||
/// Get the format for the time string
|
||||
/// </summary>
|
||||
@@ -56,18 +85,25 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
/// Returns the number week in the month (Used code from 'David Morton' from <see href="https://social.msdn.microsoft.com/Forums/vstudio/bf504bba-85cb-492d-a8f7-4ccabdf882cb/get-week-number-for-month"/>)
|
||||
/// </summary>
|
||||
/// <param name="date">date</param>
|
||||
/// <param name="formatSettingFirstDayOfWeek">Setting for the first day in the week.</param>
|
||||
/// <returns>Number of week in the month</returns>
|
||||
internal static int GetWeekOfMonth(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
|
||||
{
|
||||
DateTime beginningOfMonth = new DateTime(date.Year, date.Month, 1);
|
||||
int adjustment = 1; // We count from 1 to 7 and not from 0 to 6
|
||||
int weekCount = 1;
|
||||
|
||||
while (date.Date.AddDays(1).DayOfWeek != formatSettingFirstDayOfWeek)
|
||||
for (int i = 1; i <= date.Day; i++)
|
||||
{
|
||||
date = date.AddDays(1);
|
||||
DateTime d = new(date.Year, date.Month, i);
|
||||
|
||||
// Count week number +1 if day is the first day of a week and not day 1 of the month.
|
||||
// (If we count on day one of a month we would start the month with week number 2.)
|
||||
if (i > 1 && d.DayOfWeek == formatSettingFirstDayOfWeek)
|
||||
{
|
||||
weekCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + adjustment;
|
||||
return weekCount;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -83,40 +119,170 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
return ((date.DayOfWeek + daysInWeek - formatSettingFirstDayOfWeek) % daysInWeek) + adjustment;
|
||||
}
|
||||
|
||||
internal static double ConvertToOleAutomationFormat(DateTime date, OADateFormats type)
|
||||
{
|
||||
double v = date.ToOADate();
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case OADateFormats.Excel1904:
|
||||
// Excel with base 1904: Adjust by -1462
|
||||
v -= 1462;
|
||||
|
||||
// Date starts at 1/1/1904 = 0
|
||||
if (Math.Truncate(v) < 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Not a valid Excel date.", innerException: null);
|
||||
}
|
||||
|
||||
return v;
|
||||
case OADateFormats.Excel1900:
|
||||
// Excel with base 1900: Adjust by -1 if v < 61
|
||||
v = v < 61 ? v - 1 : v;
|
||||
|
||||
// Date starts at 1/1/1900 = 1
|
||||
if (Math.Truncate(v) < 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Not a valid Excel date.", innerException: null);
|
||||
}
|
||||
|
||||
return v;
|
||||
default:
|
||||
// OLE Automation date: Return as is.
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert input string to a <see cref="DateTime"/> object in local time
|
||||
/// </summary>
|
||||
/// <param name="input">String with date/time</param>
|
||||
/// <param name="timestamp">The new <see cref="DateTime"/> object</param>
|
||||
/// <param name="inputParsingErrorMsg">Error message shown to the user</param>
|
||||
/// <returns>True on success, otherwise false</returns>
|
||||
internal static bool ParseStringAsDateTime(in string input, out DateTime timestamp)
|
||||
internal static bool ParseStringAsDateTime(in string input, out DateTime timestamp, out string inputParsingErrorMsg)
|
||||
{
|
||||
inputParsingErrorMsg = string.Empty;
|
||||
CompositeFormat errorMessage = CompositeFormat.Parse(Resources.Microsoft_plugin_timedate_InvalidInput_SupportedRange);
|
||||
|
||||
if (DateTime.TryParse(input, out timestamp))
|
||||
{
|
||||
// Known date/time format
|
||||
return true;
|
||||
}
|
||||
else if (Regex.IsMatch(input, @"^u[\+-]?\d{1,10}$") && long.TryParse(input.TrimStart('u'), out long secondsU))
|
||||
else if (Regex.IsMatch(input, @"^u[\+-]?\d+$"))
|
||||
{
|
||||
// Unix time stamp
|
||||
// We use long instead of int, because int is too small after 03:14:07 UTC 2038-01-19
|
||||
var canParse = long.TryParse(input.TrimStart('u'), out var secondsU);
|
||||
|
||||
// Value has to be in the range from -62135596800 to 253402300799
|
||||
if (!canParse || secondsU < UnixTimeSecondsMin || secondsU > UnixTimeSecondsMax)
|
||||
{
|
||||
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Unix, UnixTimeSecondsMin, UnixTimeSecondsMax);
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
timestamp = DateTimeOffset.FromUnixTimeSeconds(secondsU).LocalDateTime;
|
||||
return true;
|
||||
}
|
||||
else if (Regex.IsMatch(input, @"^ums[\+-]?\d{1,13}$") && long.TryParse(input.TrimStart("ums".ToCharArray()), out long millisecondsUms))
|
||||
else if (Regex.IsMatch(input, @"^ums[\+-]?\d+$"))
|
||||
{
|
||||
// Unix time stamp in milliseconds
|
||||
// We use long instead of int because int is too small after 03:14:07 UTC 2038-01-19
|
||||
var canParse = long.TryParse(input.TrimStart("ums".ToCharArray()), out var millisecondsUms);
|
||||
|
||||
// Value has to be in the range from -62135596800000 to 253402300799999
|
||||
if (!canParse || millisecondsUms < UnixTimeMillisecondsMin || millisecondsUms > UnixTimeMillisecondsMax)
|
||||
{
|
||||
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Unix_Milliseconds, UnixTimeMillisecondsMin, UnixTimeMillisecondsMax);
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(millisecondsUms).LocalDateTime;
|
||||
return true;
|
||||
}
|
||||
else if (Regex.IsMatch(input, @"^ft\d+$") && long.TryParse(input.TrimStart("ft".ToCharArray()), out long secondsFt))
|
||||
else if (Regex.IsMatch(input, @"^ft\d+$"))
|
||||
{
|
||||
var canParse = long.TryParse(input.TrimStart("ft".ToCharArray()), out var secondsFt);
|
||||
|
||||
// Windows file time
|
||||
// Value has to be in the range from 0 to 2650467707991000000
|
||||
if (!canParse || secondsFt < WindowsFileTimeMin || secondsFt > WindowsFileTimeMax)
|
||||
{
|
||||
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_WindowsFileTime, WindowsFileTimeMin, WindowsFileTimeMax);
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
// DateTime.FromFileTime returns as local time.
|
||||
timestamp = DateTime.FromFileTime(secondsFt);
|
||||
return true;
|
||||
}
|
||||
else if (Regex.IsMatch(input, @"^oa[+-]?\d+[,.0-9]*$"))
|
||||
{
|
||||
var canParse = double.TryParse(input.TrimStart("oa".ToCharArray()), out var oADate);
|
||||
|
||||
// OLE Automation date
|
||||
// Input has to be in the range from -657434.99999999 to 2958465.99999999
|
||||
// DateTime.FromOADate returns as local time.
|
||||
if (!canParse || oADate < OADateMin || oADate > OADateMax)
|
||||
{
|
||||
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_OADate, OADateMin, OADateMax);
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
timestamp = DateTime.FromOADate(oADate);
|
||||
return true;
|
||||
}
|
||||
else if (Regex.IsMatch(input, @"^exc[+-]?\d+[,.0-9]*$"))
|
||||
{
|
||||
var canParse = double.TryParse(input.TrimStart("exc".ToCharArray()), out var excDate);
|
||||
|
||||
// Excel's 1900 date value
|
||||
// Input has to be in the range from 1 (0 = Fake date) to 2958465.99998843 and not 60 whole number
|
||||
// Because of a bug in Excel and the way it behaves before 3/1/1900 we have to adjust all inputs lower than 61 for +1
|
||||
// DateTime.FromOADate returns as local time.
|
||||
if (!canParse || excDate < 0 || excDate > Excel1900DateMax)
|
||||
{
|
||||
// For the if itself we use 0 as min value that we can show a special message if input is 0.
|
||||
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Excel1900, Excel1900DateMin, Excel1900DateMax);
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Math.Truncate(excDate) == 0 || Math.Truncate(excDate) == 60)
|
||||
{
|
||||
inputParsingErrorMsg = Resources.Microsoft_plugin_timedate_InvalidInput_FakeExcel1900;
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
excDate = excDate <= 60 ? excDate + 1 : excDate;
|
||||
timestamp = DateTime.FromOADate(excDate);
|
||||
return true;
|
||||
}
|
||||
else if (Regex.IsMatch(input, @"^exf[+-]?\d+[,.0-9]*$"))
|
||||
{
|
||||
var canParse = double.TryParse(input.TrimStart("exf".ToCharArray()), out var exfDate);
|
||||
|
||||
// Excel's 1904 date value
|
||||
// Input has to be in the range from 0 to 2957003.99998843
|
||||
// Because Excel uses 01/01/1904 as base we need to adjust for +1462
|
||||
// DateTime.FromOADate returns as local time.
|
||||
if (!canParse || exfDate < Excel1904DateMin || exfDate > Excel1904DateMax)
|
||||
{
|
||||
inputParsingErrorMsg = string.Format(CultureInfo.CurrentCulture, errorMessage, Resources.Microsoft_plugin_timedate_Excel1904, Excel1904DateMin, Excel1904DateMax);
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
timestamp = DateTime.FromOADate(exfDate + 1462);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||
@@ -125,13 +291,85 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if input is special parsing for Unix time, Unix time in milliseconds or File time.
|
||||
/// Test if input is special parsing for Unix time, Unix time in milliseconds, file time, ...
|
||||
/// </summary>
|
||||
/// <param name="input">String with date/time</param>
|
||||
/// <returns>True if yes, otherwise false</returns>
|
||||
internal static bool IsSpecialInputParsing(string input)
|
||||
{
|
||||
return Regex.IsMatch(input, @"^.*(u|ums|ft)\d");
|
||||
return _regexSpecialInputFormats.IsMatch(input);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a DateTime object based on the format string
|
||||
/// </summary>
|
||||
/// <param name="date">Date/time object.</param>
|
||||
/// <param name="unix">Value for replacing "Unix Time Stamp".</param>
|
||||
/// <param name="unixMilliseconds">Value for replacing "Unix Time Stamp in milliseconds".</param>
|
||||
/// <param name="calWeek">Value for relacing calendar week.</param>
|
||||
/// <param name="eraShortFormat">Era abbreviation.</param>
|
||||
/// <param name="format">Format definition.</param>
|
||||
/// <returns>Formated date/time string.</returns>
|
||||
internal static string ConvertToCustomFormat(DateTime date, long unix, long unixMilliseconds, int calWeek, string eraShortFormat, string format, CalendarWeekRule firstWeekRule, DayOfWeek firstDayOfTheWeek)
|
||||
{
|
||||
string result = format;
|
||||
|
||||
// DOW: Number of day in week
|
||||
result = _regexCustomDateTimeDow.Replace(result, GetNumberOfDayInWeek(date, firstDayOfTheWeek).ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// DIM: Days in Month
|
||||
result = _regexCustomDateTimeDim.Replace(result, DateTime.DaysInMonth(date.Year, date.Month).ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// WOM: Week of Month
|
||||
result = _regexCustomDateTimeWom.Replace(result, GetWeekOfMonth(date, firstDayOfTheWeek).ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// WOY: Week of Year
|
||||
result = _regexCustomDateTimeWoy.Replace(result, calWeek.ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// EAB: Era abbreviation
|
||||
result = _regexCustomDateTimeEab.Replace(result, eraShortFormat);
|
||||
|
||||
// WFT: Week of Month
|
||||
if (_regexCustomDateTimeWft.IsMatch(result))
|
||||
{
|
||||
// Special handling as very early dates can't convert.
|
||||
result = _regexCustomDateTimeWft.Replace(result, date.ToFileTime().ToString(CultureInfo.CurrentCulture));
|
||||
}
|
||||
|
||||
// UXT: Unix time stamp
|
||||
result = _regexCustomDateTimeUxt.Replace(result, unix.ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// UMS: Unix time stamp milli seconds
|
||||
result = _regexCustomDateTimeUms.Replace(result, unixMilliseconds.ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// OAD: OLE Automation date
|
||||
result = _regexCustomDateTimeOad.Replace(result, ConvertToOleAutomationFormat(date, OADateFormats.OLEAutomation).ToString(CultureInfo.CurrentCulture));
|
||||
|
||||
// EXC: Excel date value with base 1900
|
||||
if (_regexCustomDateTimeExc.IsMatch(result))
|
||||
{
|
||||
// Special handling as very early dates can't convert.
|
||||
result = _regexCustomDateTimeExc.Replace(result, ConvertToOleAutomationFormat(date, OADateFormats.Excel1900).ToString(CultureInfo.CurrentCulture));
|
||||
}
|
||||
|
||||
// EXF: Excel date value with base 1904
|
||||
if (_regexCustomDateTimeExf.IsMatch(result))
|
||||
{
|
||||
// Special handling as very early dates can't convert.
|
||||
result = _regexCustomDateTimeExf.Replace(result, ConvertToOleAutomationFormat(date, OADateFormats.Excel1904).ToString(CultureInfo.CurrentCulture));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test a string for our custom date and time format syntax
|
||||
/// </summary>
|
||||
/// <param name="str">String to test.</param>
|
||||
/// <returns>True if yes and otherwise false</returns>
|
||||
internal static bool StringContainsCustomFormatSyntax(string str)
|
||||
{
|
||||
return _regexCustomDateTimeFormats.IsMatch(str);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -190,4 +428,14 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
Date,
|
||||
DateTime,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Different versions of Date formats based on OLE Automation date
|
||||
/// </summary>
|
||||
internal enum OADateFormats
|
||||
{
|
||||
OLEAutomation,
|
||||
Excel1900,
|
||||
Excel1904,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,11 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
/// </summary>
|
||||
internal bool HideNumberMessageOnGlobalQuery { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value containing the custom format definitions
|
||||
/// </summary>
|
||||
internal List<string> CustomFormats { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TimeDateSettings"/> class.
|
||||
/// Private constructor to make sure there is never more than one instance of this class
|
||||
@@ -100,29 +105,6 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
{
|
||||
var optionList = new List<PluginAdditionalOption>
|
||||
{
|
||||
new PluginAdditionalOption()
|
||||
{
|
||||
Key = nameof(CalendarFirstWeekRule),
|
||||
DisplayLabel = Resources.Microsoft_plugin_timedate_SettingFirstWeekRule,
|
||||
DisplayDescription = Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_Description,
|
||||
PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Combobox,
|
||||
ComboBoxItems = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_Setting_UseSystemSetting, "-1"),
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstDay, "0"),
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstFullWeek, "1"),
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstFourDayWeek, "2"),
|
||||
},
|
||||
ComboBoxValue = -1,
|
||||
},
|
||||
new PluginAdditionalOption()
|
||||
{
|
||||
Key = nameof(FirstDayOfWeek),
|
||||
DisplayLabel = Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek,
|
||||
PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Combobox,
|
||||
ComboBoxItems = GetSortedListForWeekDaySetting(),
|
||||
ComboBoxValue = -1,
|
||||
},
|
||||
new PluginAdditionalOption()
|
||||
{
|
||||
Key = nameof(OnlyDateTimeNowGlobal),
|
||||
@@ -150,6 +132,38 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
DisplayLabel = Resources.Microsoft_plugin_timedate_SettingHideNumberMessageOnGlobalQuery,
|
||||
Value = false,
|
||||
},
|
||||
new PluginAdditionalOption()
|
||||
{
|
||||
Key = nameof(CalendarFirstWeekRule),
|
||||
DisplayLabel = Resources.Microsoft_plugin_timedate_SettingFirstWeekRule,
|
||||
DisplayDescription = Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_Description,
|
||||
PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Combobox,
|
||||
ComboBoxItems = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_Setting_UseSystemSetting, "-1"),
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstDay, "0"),
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstFullWeek, "1"),
|
||||
new KeyValuePair<string, string>(Resources.Microsoft_plugin_timedate_SettingFirstWeekRule_FirstFourDayWeek, "2"),
|
||||
},
|
||||
ComboBoxValue = -1,
|
||||
},
|
||||
new PluginAdditionalOption()
|
||||
{
|
||||
Key = nameof(FirstDayOfWeek),
|
||||
DisplayLabel = Resources.Microsoft_plugin_timedate_SettingFirstDayOfWeek,
|
||||
PluginOptionType = PluginAdditionalOption.AdditionalOptionType.Combobox,
|
||||
ComboBoxItems = GetSortedListForWeekDaySetting(),
|
||||
ComboBoxValue = -1,
|
||||
},
|
||||
new PluginAdditionalOption()
|
||||
{
|
||||
Key = nameof(CustomFormats),
|
||||
PluginOptionType = PluginAdditionalOption.AdditionalOptionType.MultilineTextbox,
|
||||
DisplayLabel = Resources.Microsoft_plugin_timedate_Setting_CustomFormats,
|
||||
DisplayDescription = string.Format(CultureInfo.CurrentCulture, Resources.Microsoft_plugin_timedate_Setting_CustomFormatsDescription.ToString(), "DOW", "DIM", "WOM", "WOY", "EAB", "WFT", "UXT", "UMS", "OAD", "EXC", "EXF", "UTC:"),
|
||||
PlaceholderText = "MyFormat=dd-MMM-yyyy\rMySecondFormat=dddd (Da\\y nu\\mber: DOW)\rMyUtcFormat=UTC:hh:mm:ss",
|
||||
TextValue = string.Empty,
|
||||
},
|
||||
};
|
||||
|
||||
return optionList;
|
||||
@@ -172,6 +186,7 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
TimeWithSeconds = GetSettingOrDefault(settings, nameof(TimeWithSeconds));
|
||||
DateWithWeekday = GetSettingOrDefault(settings, nameof(DateWithWeekday));
|
||||
HideNumberMessageOnGlobalQuery = GetSettingOrDefault(settings, nameof(HideNumberMessageOnGlobalQuery));
|
||||
CustomFormats = GetMultilineTextSettingOrDefault(settings, nameof(CustomFormats));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -204,6 +219,21 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
||||
return option?.ComboBoxValue ?? GetAdditionalOptions().First(x => x.Key == name).ComboBoxValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the combobox value of the given settings list with the given name.
|
||||
/// </summary>
|
||||
/// <param name="settings">The object that contain all settings.</param>
|
||||
/// <param name="name">The name of the setting.</param>
|
||||
/// <returns>A settings value.</returns>
|
||||
private static List<string> GetMultilineTextSettingOrDefault(PowerLauncherPluginSettings settings, string name)
|
||||
{
|
||||
var option = settings?.AdditionalOptions?.FirstOrDefault(x => x.Key == name);
|
||||
|
||||
// If a setting isn't available, we use the value defined in the method GetAdditionalOptions() as fallback.
|
||||
// We can use First() instead of FirstOrDefault() because the values must exist. Otherwise, we made a mistake when defining the settings.
|
||||
return option?.TextValueAsMultilineList ?? GetAdditionalOptions().First(x => x.Key == name).TextValueAsMultilineList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a sorted list of values for the combo box of 'first day of week' setting.
|
||||
/// The list is sorted based on the current system culture setting.
|
||||
|
||||
@@ -150,6 +150,15 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Days in month.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_DaysInMonth {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_DaysInMonth", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Era.
|
||||
/// </summary>
|
||||
@@ -169,7 +178,25 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Valid prefixes: 'u' for Unix Timestamp, 'ums' for Unix Timestamp in milliseconds, 'ft' for Windows file time.
|
||||
/// Looks up a localized string similar to Failed to convert into custom format:.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_ErrorConvertCustomFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_ErrorConvertCustomFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not a valid Windows file time.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_ErrorConvertWft {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_ErrorConvertWft", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Valid prefixes: 'u' for Unix Timestamp, 'ums' for Unix Timestamp in milliseconds, 'ft' for Windows file time, 'oa' for OLE Automation date, 'exc' for Excel's 1900 date value, 'exf' for Excel's 1904 date value.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_ErrorResultSubTitle {
|
||||
get {
|
||||
@@ -178,7 +205,7 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error: Invalid number input.
|
||||
/// Looks up a localized string similar to Error: Invalid input.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_ErrorResultTitle {
|
||||
get {
|
||||
@@ -186,6 +213,33 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Error: Invalid number.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_ErrorResultValue {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_ErrorResultValue", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Excel's 1900 date value.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_Excel1900 {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_Excel1900", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Excel's 1904 date value.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_Excel1904 {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_Excel1904", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Date and time in filename-compatible format.
|
||||
/// </summary>
|
||||
@@ -204,6 +258,33 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Invalid custom format:.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_InvalidCustomFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidCustomFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cannot parse the input as Excel's 1900 date value because it is a fake date. (In Excel 0 stands for 0/1/1900 and this date doesn't exist. And 60 stands for 2/29/1900 and this date only exists in Excel for compatibility with Lotus 123.).
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_InvalidInput_FakeExcel1900 {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidInput_FakeExcel1900", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Your input for {0} is outside the range from {1} to {2}..
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_InvalidInput_SupportedRange {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidInput_SupportedRange", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ISO 8601.
|
||||
/// </summary>
|
||||
@@ -240,6 +321,15 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Leap year.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_LeapYear {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_LeapYear", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Millisecond.
|
||||
/// </summary>
|
||||
@@ -285,6 +375,15 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Not a leap year.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_NoLeapYear {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_NoLeapYear", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Now.
|
||||
/// </summary>
|
||||
@@ -303,6 +402,15 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OLE Automation Date.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_OADate {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_OADate", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Provides time and date values for the system time or a custom time stamp (e.g.'{0}', '{1}', '{2}', '{3}').
|
||||
/// </summary>
|
||||
@@ -366,6 +474,42 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Date and time; Time and Date; Custom format.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_SearchTagCustom {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_SearchTagCustom", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Current date and time; Current time and date; Now; Custom format.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_SearchTagCustomNow {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_SearchTagCustomNow", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Date and time UTC; Time UTC and Date; Custom UTC format.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_SearchTagCustomUtc {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_SearchTagCustomUtc", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Current date and time UTC; Current time UTC and date; Now UTC; Custom UTC format.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_SearchTagCustomUtcNow {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_SearchTagCustomUtcNow", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Date.
|
||||
/// </summary>
|
||||
@@ -447,6 +591,24 @@ namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Custom formats.
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_Setting_CustomFormats {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_Setting_CustomFormats", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Use date and time string format syntax and {0} (Day of Week), {1} (Days in Month), {2} (Week of Month), {3} (Week of the year), {4} (Era abbreviation), {5} (Windows File Time), {6} (Unix Time), {7} (Unix Time in milliseconds), {8} (OLE Automation date), {9} (Excel's 1900 based date value), {10} (Excel's 1904 based date value). If the format starts with {11}, then Universal Time (UTC) is used. (Use a backslash to escape format sequences and the backslash character as text.).
|
||||
/// </summary>
|
||||
internal static string Microsoft_plugin_timedate_Setting_CustomFormatsDescription {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_timedate_Setting_CustomFormatsDescription", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Use system setting.
|
||||
/// </summary>
|
||||
|
||||
@@ -156,10 +156,13 @@
|
||||
<value>Era abbreviation</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_ErrorResultSubTitle" xml:space="preserve">
|
||||
<value>Valid prefixes: 'u' for Unix Timestamp, 'ums' for Unix Timestamp in milliseconds, 'ft' for Windows file time</value>
|
||||
<value>Valid prefixes: 'u' for Unix Timestamp, 'ums' for Unix Timestamp in milliseconds, 'ft' for Windows file time, 'oa' for OLE Automation date, 'exc' for Excel's 1900 date value, 'exf' for Excel's 1904 date value</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_ErrorResultTitle" xml:space="preserve">
|
||||
<value>Error: Invalid number input</value>
|
||||
<value>Error: Invalid input</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_ErrorResultValue" xml:space="preserve">
|
||||
<value>Error: Invalid number</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_Hour" xml:space="preserve">
|
||||
<value>Hour</value>
|
||||
@@ -243,10 +246,26 @@
|
||||
<value>Date and time; Time and Date</value>
|
||||
<comment>Don't change order</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_SearchTagCustom" xml:space="preserve">
|
||||
<value>Date and time; Time and Date; Custom format</value>
|
||||
<comment>Don't change order</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_SearchTagCustomUtc" xml:space="preserve">
|
||||
<value>Date and time UTC; Time UTC and Date; Custom UTC format</value>
|
||||
<comment>Don't change order</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_SearchTagFormatNow" xml:space="preserve">
|
||||
<value>Current date and time; Current time and date; Now</value>
|
||||
<comment>Don't change order</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_SearchTagCustomNow" xml:space="preserve">
|
||||
<value>Current date and time; Current time and date; Now; Custom format</value>
|
||||
<comment>Don't change order</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_SearchTagCustomUtcNow" xml:space="preserve">
|
||||
<value>Current date and time UTC; Current time UTC and date; Now UTC; Custom UTC format</value>
|
||||
<comment>Don't change order</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_SearchTagTime" xml:space="preserve">
|
||||
<value>Time</value>
|
||||
<comment>Don't change order</comment>
|
||||
@@ -262,6 +281,9 @@
|
||||
<data name="Microsoft_plugin_timedate_Second" xml:space="preserve">
|
||||
<value>Second</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_InvalidCustomFormat" xml:space="preserve">
|
||||
<value>Invalid custom format:</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_SettingDateWithWeekday" xml:space="preserve">
|
||||
<value>Show date with weekday and name of month</value>
|
||||
</data>
|
||||
@@ -360,4 +382,42 @@
|
||||
<data name="Microsoft_plugin_timedate_Setting_UseSystemSetting" xml:space="preserve">
|
||||
<value>Use system setting</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_Setting_CustomFormats" xml:space="preserve">
|
||||
<value>Custom formats</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_Setting_CustomFormatsDescription" xml:space="preserve">
|
||||
<value>Use date and time string format syntax and {0} (Day of Week), {1} (Days in Month), {2} (Week of Month), {3} (Week of the year), {4} (Era abbreviation), {5} (Windows File Time), {6} (Unix Time), {7} (Unix Time in milliseconds), {8} (OLE Automation date), {9} (Excel's 1900 based date value), {10} (Excel's 1904 based date value). If the format starts with {11}, then Universal Time (UTC) is used. (Use a backslash to escape format sequences and the backslash character as text.)</value>
|
||||
<comment>The {n} parts are place holders and get replaced in the code.</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_ErrorConvertCustomFormat" xml:space="preserve">
|
||||
<value>Failed to convert into custom format:</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_ErrorConvertWft" xml:space="preserve">
|
||||
<value>Not a valid Windows file time</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_InvalidInput_SupportedRange" xml:space="preserve">
|
||||
<value>Your input for {0} is outside the range from {1} to {2}.</value>
|
||||
<comment>The placeholder will be replace in code.</comment>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_OADate" xml:space="preserve">
|
||||
<value>OLE Automation Date</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_Excel1900" xml:space="preserve">
|
||||
<value>Excel's 1900 date value</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_InvalidInput_FakeExcel1900" xml:space="preserve">
|
||||
<value>Cannot parse the input as Excel's 1900 date value because it is a fake date. (In Excel 0 stands for 0/1/1900 and this date doesn't exist. And 60 stands for 2/29/1900 and this date only exists in Excel for compatibility with Lotus 123.)</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_Excel1904" xml:space="preserve">
|
||||
<value>Excel's 1904 date value</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_LeapYear" xml:space="preserve">
|
||||
<value>Leap year</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_NoLeapYear" xml:space="preserve">
|
||||
<value>Not a leap year</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_timedate_DaysInMonth" xml:space="preserve">
|
||||
<value>Days in month</value>
|
||||
</data>
|
||||
</root>
|
||||
Reference in New Issue
Block a user