mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
[CmdPalette > Time and Date] Custom formats (Port #37743) and other plugin improvements - 2 (#38952)
* port changes from broken PR * fixes * fix formatting
This commit is contained in:
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@@ -273,6 +273,7 @@ CURSORINFO
|
|||||||
cursorpos
|
cursorpos
|
||||||
customaction
|
customaction
|
||||||
CUSTOMACTIONTEST
|
CUSTOMACTIONTEST
|
||||||
|
CUSTOMFORMATPLACEHOLDER
|
||||||
CVal
|
CVal
|
||||||
cvd
|
cvd
|
||||||
CVirtual
|
CVirtual
|
||||||
@@ -1648,6 +1649,7 @@ telephon
|
|||||||
templatenamespace
|
templatenamespace
|
||||||
testprocess
|
testprocess
|
||||||
TEXCOORD
|
TEXCOORD
|
||||||
|
TEXTBOXNEWLINE
|
||||||
TEXTEXTRACTOR
|
TEXTEXTRACTOR
|
||||||
TEXTINCLUDE
|
TEXTINCLUDE
|
||||||
tfopen
|
tfopen
|
||||||
|
|||||||
@@ -4,11 +4,9 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||||
|
|
||||||
[assembly: InternalsVisibleTo("Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests")]
|
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
||||||
|
|
||||||
internal class AvailableResult
|
internal sealed class AvailableResult
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the time/date value
|
/// Gets or sets the time/date value
|
||||||
@@ -30,6 +28,11 @@ internal class AvailableResult
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal ResultIconType IconType { get; set; }
|
internal ResultIconType IconType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value to show additional error details
|
||||||
|
/// </summary>
|
||||||
|
internal string ErrorDetails { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the path to the icon
|
/// Returns the path to the icon
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -42,6 +45,7 @@ internal class AvailableResult
|
|||||||
ResultIconType.Time => ResultHelper.TimeIcon,
|
ResultIconType.Time => ResultHelper.TimeIcon,
|
||||||
ResultIconType.Date => ResultHelper.CalendarIcon,
|
ResultIconType.Date => ResultHelper.CalendarIcon,
|
||||||
ResultIconType.DateTime => ResultHelper.TimeDateIcon,
|
ResultIconType.DateTime => ResultHelper.TimeDateIcon,
|
||||||
|
ResultIconType.Error => ResultHelper.ErrorIcon,
|
||||||
_ => null,
|
_ => null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -53,6 +57,7 @@ internal class AvailableResult
|
|||||||
Title = this.Value,
|
Title = this.Value,
|
||||||
Subtitle = this.Label,
|
Subtitle = this.Label,
|
||||||
Icon = this.GetIconInfo(),
|
Icon = this.GetIconInfo(),
|
||||||
|
Details = string.IsNullOrEmpty(this.ErrorDetails) ? null : new Details() { Body = this.ErrorDetails },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,4 +86,5 @@ public enum ResultIconType
|
|||||||
Time,
|
Time,
|
||||||
Date,
|
Date,
|
||||||
DateTime,
|
DateTime,
|
||||||
|
Error,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
||||||
|
|
||||||
@@ -69,6 +70,86 @@ internal static class AvailableResultsList
|
|||||||
var era = DateTimeFormatInfo.CurrentInfo.GetEraName(calendar.GetEra(dateTimeNow));
|
var era = DateTimeFormatInfo.CurrentInfo.GetEraName(calendar.GetEra(dateTimeNow));
|
||||||
var eraShort = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedEraName(calendar.GetEra(dateTimeNow));
|
var eraShort = DateTimeFormatInfo.CurrentInfo.GetAbbreviatedEraName(calendar.GetEra(dateTimeNow));
|
||||||
|
|
||||||
|
// Custom formats
|
||||||
|
foreach (var f in settings.CustomFormats)
|
||||||
|
{
|
||||||
|
var formatParts = f.Split("=", 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
var formatSyntax = formatParts.Length == 2 ? formatParts[1] : string.Empty;
|
||||||
|
var searchTags = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagCustom");
|
||||||
|
var 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.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var 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)
|
||||||
|
{
|
||||||
|
results.Add(new AvailableResult()
|
||||||
|
{
|
||||||
|
Value = Resources.Microsoft_plugin_timedate_ErrorConvertCustomFormat,
|
||||||
|
Label = formatParts[0] + " - " + Resources.Microsoft_plugin_timedate_show_details,
|
||||||
|
AlternativeSearchTag = searchTags,
|
||||||
|
IconType = ResultIconType.Error,
|
||||||
|
ErrorDetails = e.Message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
results.Add(new AvailableResult()
|
||||||
|
{
|
||||||
|
Value = Resources.Microsoft_plugin_timedate_InvalidCustomFormat + " " + formatSyntax,
|
||||||
|
Label = formatParts[0] + " - " + Resources.Microsoft_plugin_timedate_show_details,
|
||||||
|
AlternativeSearchTag = searchTags,
|
||||||
|
IconType = ResultIconType.Error,
|
||||||
|
ErrorDetails = e.Message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Predefined formats
|
||||||
results.AddRange(new[]
|
results.AddRange(new[]
|
||||||
{
|
{
|
||||||
new AvailableResult()
|
new AvailableResult()
|
||||||
@@ -149,6 +230,13 @@ internal static class AvailableResultsList
|
|||||||
IconType = ResultIconType.Date,
|
IconType = ResultIconType.Date,
|
||||||
},
|
},
|
||||||
new AvailableResult()
|
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),
|
Value = dateTimeNow.DayOfYear.ToString(CultureInfo.CurrentCulture),
|
||||||
Label = Resources.Microsoft_plugin_timedate_DayOfYear,
|
Label = Resources.Microsoft_plugin_timedate_DayOfYear,
|
||||||
@@ -198,6 +286,13 @@ internal static class AvailableResultsList
|
|||||||
IconType = ResultIconType.Date,
|
IconType = ResultIconType.Date,
|
||||||
},
|
},
|
||||||
new AvailableResult()
|
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,
|
Value = era,
|
||||||
Label = Resources.Microsoft_plugin_timedate_Era,
|
Label = Resources.Microsoft_plugin_timedate_Era,
|
||||||
@@ -218,13 +313,31 @@ internal static class AvailableResultsList
|
|||||||
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
|
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagDate"),
|
||||||
IconType = ResultIconType.Date,
|
IconType = ResultIconType.Date,
|
||||||
},
|
},
|
||||||
new AvailableResult()
|
});
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
results.Add(new AvailableResult()
|
||||||
{
|
{
|
||||||
Value = dateTimeNow.ToFileTime().ToString(CultureInfo.CurrentCulture),
|
Value = dateTimeNow.ToFileTime().ToString(CultureInfo.CurrentCulture),
|
||||||
Label = Resources.Microsoft_plugin_timedate_WindowsFileTime,
|
Label = Resources.Microsoft_plugin_timedate_WindowsFileTime,
|
||||||
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
|
AlternativeSearchTag = ResultHelper.SelectStringFromResources(isSystemDateTime, "Microsoft_plugin_timedate_SearchTagFormat"),
|
||||||
IconType = ResultIconType.DateTime,
|
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()
|
new AvailableResult()
|
||||||
{
|
{
|
||||||
Value = dateTimeNowUtc.ToString("u"),
|
Value = dateTimeNowUtc.ToString("u"),
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||||
// See the LICENSE file in the project root for more information.
|
// See the LICENSE file in the project root for more information.
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using Microsoft.CommandPalette.Extensions;
|
||||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
||||||
@@ -33,21 +32,24 @@ internal static class ResultHelper
|
|||||||
|
|
||||||
public static IconInfo TimeDateIcon { get; } = new IconInfo("\uEC92");
|
public static IconInfo TimeDateIcon { get; } = new IconInfo("\uEC92");
|
||||||
|
|
||||||
|
public static IconInfo ErrorIcon { get; } = IconHelpers.FromRelativePaths("Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.light.png", "Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.dark.png");
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a result with an error message that only numbers can't be parsed
|
/// Gets a result with an error message that input can't be parsed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Element of type <see cref="Result"/>.</returns>
|
/// <returns>Element of type <see cref="Result"/>.</returns>
|
||||||
internal static ListItem CreateNumberErrorResult() => new ListItem(new NoOpCommand())
|
#pragma warning disable CA1863 // Use 'CompositeFormat'
|
||||||
{
|
|
||||||
Title = Resources.Microsoft_plugin_timedate_ErrorResultTitle,
|
|
||||||
Subtitle = Resources.Microsoft_plugin_timedate_ErrorResultSubTitle,
|
|
||||||
Icon = IconHelpers.FromRelativePaths("Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.light.png", "Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.dark.png"),
|
|
||||||
};
|
|
||||||
|
|
||||||
internal static ListItem CreateInvalidInputErrorResult() => new ListItem(new NoOpCommand())
|
internal static ListItem CreateInvalidInputErrorResult() => new ListItem(new NoOpCommand())
|
||||||
{
|
{
|
||||||
Title = Resources.Microsoft_plugin_timedate_InvalidInput_ErrorMessageTitle,
|
Title = Resources.Microsoft_plugin_timedate_InvalidInput_ErrorMessageTitle,
|
||||||
Subtitle = Resources.Microsoft_plugin_timedate_InvalidInput_ErrorMessageSubTitle,
|
Icon = ErrorIcon,
|
||||||
Icon = IconHelpers.FromRelativePaths("Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.light.png", "Microsoft.CmdPal.Ext.TimeDate\\Assets\\Warning.dark.png"),
|
Details = new Details()
|
||||||
|
{
|
||||||
|
Title = Resources.Microsoft_plugin_timedate_InvalidInput_DetailsHeader,
|
||||||
|
|
||||||
|
// Because of translation we can't use 'CompositeFormat'.
|
||||||
|
Body = string.Format(CultureInfo.CurrentCulture, Resources.Microsoft_plugin_timedate_InvalidInput_SupportedInput, "**", "\n\n", "\n\n* "),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
#pragma warning restore CA1863 // Use 'CompositeFormat'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
|||||||
|
|
||||||
public class SettingsManager : JsonSettingsManager
|
public class SettingsManager : JsonSettingsManager
|
||||||
{
|
{
|
||||||
|
// Line break character used in WinUI3 TextBox and TextBlock.
|
||||||
|
private const char TEXTBOXNEWLINE = '\r';
|
||||||
|
|
||||||
|
private const string CUSTOMFORMATPLACEHOLDER = "MyFormat=dd-MMM-yyyy\rMySecondFormat=dddd (Da\\y nu\\mber: DOW)\rMyUtcFormat=UTC:hh:mm:ss";
|
||||||
|
|
||||||
private static readonly string _namespace = "timeDate";
|
private static readonly string _namespace = "timeDate";
|
||||||
|
|
||||||
private static string Namespaced(string propertyName) => $"{_namespace}.{propertyName}";
|
private static string Namespaced(string propertyName) => $"{_namespace}.{propertyName}";
|
||||||
@@ -94,6 +99,12 @@ public class SettingsManager : JsonSettingsManager
|
|||||||
Resources.Microsoft_plugin_timedate_SettingHideNumberMessageOnGlobalQuery,
|
Resources.Microsoft_plugin_timedate_SettingHideNumberMessageOnGlobalQuery,
|
||||||
true); // TODO -- double check default value
|
true); // TODO -- double check default value
|
||||||
|
|
||||||
|
private readonly TextSetting _customFormats = new(
|
||||||
|
Namespaced(nameof(CustomFormats)),
|
||||||
|
Resources.Microsoft_plugin_timedate_Setting_CustomFormats,
|
||||||
|
Resources.Microsoft_plugin_timedate_Setting_CustomFormats + TEXTBOXNEWLINE + string.Format(CultureInfo.CurrentCulture, Resources.Microsoft_plugin_timedate_Setting_CustomFormatsDescription.ToString(), "DOW", "DIM", "WOM", "WOY", "EAB", "WFT", "UXT", "UMS", "OAD", "EXC", "EXF", "UTC:"),
|
||||||
|
string.Empty);
|
||||||
|
|
||||||
public int FirstWeekOfYear
|
public int FirstWeekOfYear
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -142,6 +153,8 @@ public class SettingsManager : JsonSettingsManager
|
|||||||
|
|
||||||
public bool HideNumberMessageOnGlobalQuery => _hideNumberMessageOnGlobalQuery.Value;
|
public bool HideNumberMessageOnGlobalQuery => _hideNumberMessageOnGlobalQuery.Value;
|
||||||
|
|
||||||
|
public List<string> CustomFormats => _customFormats.Value.Split(TEXTBOXNEWLINE).ToList();
|
||||||
|
|
||||||
internal static string SettingsJsonPath()
|
internal static string SettingsJsonPath()
|
||||||
{
|
{
|
||||||
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
|
var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal");
|
||||||
@@ -155,12 +168,18 @@ public class SettingsManager : JsonSettingsManager
|
|||||||
{
|
{
|
||||||
FilePath = SettingsJsonPath();
|
FilePath = SettingsJsonPath();
|
||||||
|
|
||||||
Settings.Add(_firstWeekOfYear);
|
/* The following two settings make no sense with current CmdPal behavior.
|
||||||
Settings.Add(_firstDayOfWeek);
|
|
||||||
Settings.Add(_onlyDateTimeNowGlobal);
|
Settings.Add(_onlyDateTimeNowGlobal);
|
||||||
|
Settings.Add(_hideNumberMessageOnGlobalQuery); */
|
||||||
|
|
||||||
Settings.Add(_timeWithSeconds);
|
Settings.Add(_timeWithSeconds);
|
||||||
Settings.Add(_dateWithWeekday);
|
Settings.Add(_dateWithWeekday);
|
||||||
Settings.Add(_hideNumberMessageOnGlobalQuery);
|
Settings.Add(_firstWeekOfYear);
|
||||||
|
Settings.Add(_firstDayOfWeek);
|
||||||
|
|
||||||
|
_customFormats.Multiline = true;
|
||||||
|
_customFormats.Placeholder = CUSTOMFORMATPLACEHOLDER;
|
||||||
|
Settings.Add(_customFormats);
|
||||||
|
|
||||||
// Load settings from file upon initialization
|
// Load settings from file upon initialization
|
||||||
LoadSettings();
|
LoadSettings();
|
||||||
|
|||||||
@@ -4,12 +4,42 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
namespace Microsoft.CmdPal.Ext.TimeDate.Helpers;
|
||||||
|
|
||||||
internal static class TimeAndDateHelper
|
internal static class TimeAndDateHelper
|
||||||
{
|
{
|
||||||
|
/* htcfreek:Currently not used.
|
||||||
|
* 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 _regexCustomDateTimeDim = new Regex(@"(?<!\\)DIM");
|
||||||
|
private static readonly Regex _regexCustomDateTimeDow = new Regex(@"(?<!\\)DOW");
|
||||||
|
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>
|
/// <summary>
|
||||||
/// Get the format for the time string
|
/// Get the format for the time string
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -53,18 +83,25 @@ internal static class TimeAndDateHelper
|
|||||||
/// 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"/>)
|
/// 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>
|
/// </summary>
|
||||||
/// <param name="date">date</param>
|
/// <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>
|
/// <returns>Number of week in the month</returns>
|
||||||
internal static int GetWeekOfMonth(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
|
internal static int GetWeekOfMonth(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
|
||||||
{
|
{
|
||||||
var beginningOfMonth = new DateTime(date.Year, date.Month, 1);
|
var weekCount = 1;
|
||||||
var adjustment = 1; // We count from 1 to 7 and not from 0 to 6
|
|
||||||
|
|
||||||
while (date.Date.AddDays(1).DayOfWeek != formatSettingFirstDayOfWeek)
|
for (var 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>
|
/// <summary>
|
||||||
@@ -80,40 +117,170 @@ internal static class TimeAndDateHelper
|
|||||||
return ((date.DayOfWeek + daysInWeek - formatSettingFirstDayOfWeek) % daysInWeek) + adjustment;
|
return ((date.DayOfWeek + daysInWeek - formatSettingFirstDayOfWeek) % daysInWeek) + adjustment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static double ConvertToOleAutomationFormat(DateTime date, OADateFormats type)
|
||||||
|
{
|
||||||
|
var 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>
|
/// <summary>
|
||||||
/// Convert input string to a <see cref="DateTime"/> object in local time
|
/// Convert input string to a <see cref="DateTime"/> object in local time
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">String with date/time</param>
|
/// <param name="input">String with date/time</param>
|
||||||
/// <param name="timestamp">The new <see cref="DateTime"/> object</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>
|
/// <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))
|
if (DateTime.TryParse(input, out timestamp))
|
||||||
{
|
{
|
||||||
// Known date/time format
|
// Known date/time format
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (Regex.IsMatch(input, @"^u[\+-]?\d{1,10}$") && long.TryParse(input.TrimStart('u'), out var secondsU))
|
else if (Regex.IsMatch(input, @"^u[\+-]?\d+$"))
|
||||||
{
|
{
|
||||||
// Unix time stamp
|
// Unix time stamp
|
||||||
// We use long instead of int, because int is too small after 03:14:07 UTC 2038-01-19
|
// 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;
|
timestamp = DateTimeOffset.FromUnixTimeSeconds(secondsU).LocalDateTime;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (Regex.IsMatch(input, @"^ums[\+-]?\d{1,13}$") && long.TryParse(input.TrimStart("ums".ToCharArray()), out var millisecondsUms))
|
else if (Regex.IsMatch(input, @"^ums[\+-]?\d+$"))
|
||||||
{
|
{
|
||||||
// Unix time stamp in milliseconds
|
// Unix time stamp in milliseconds
|
||||||
// We use long instead of int because int is too small after 03:14:07 UTC 2038-01-19
|
// 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;
|
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(millisecondsUms).LocalDateTime;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (Regex.IsMatch(input, @"^ft\d+$") && long.TryParse(input.TrimStart("ft".ToCharArray()), out var secondsFt))
|
else if (Regex.IsMatch(input, @"^ft\d+$"))
|
||||||
{
|
{
|
||||||
|
var canParse = long.TryParse(input.TrimStart("ft".ToCharArray()), out var secondsFt);
|
||||||
|
|
||||||
// Windows file time
|
// 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.
|
// DateTime.FromFileTime returns as local time.
|
||||||
timestamp = DateTime.FromFileTime(secondsFt);
|
timestamp = DateTime.FromFileTime(secondsFt);
|
||||||
return true;
|
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
|
else
|
||||||
{
|
{
|
||||||
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
||||||
@@ -121,14 +288,87 @@ internal static class TimeAndDateHelper
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* htcfreek:Currently not required
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
/// <param name="input">String with date/time</param>
|
/// <param name="input">String with date/time</param>
|
||||||
/// <returns>True if yes, otherwise false</returns>
|
/// <returns>True if yes, otherwise false</returns>
|
||||||
internal static bool IsSpecialInputParsing(string input)
|
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)
|
||||||
|
{
|
||||||
|
var 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>
|
/// <summary>
|
||||||
@@ -187,3 +427,13 @@ internal enum FormatStringType
|
|||||||
Date,
|
Date,
|
||||||
DateTime,
|
DateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Different versions of Date formats based on OLE Automation date
|
||||||
|
/// </summary>
|
||||||
|
internal enum OADateFormats
|
||||||
|
{
|
||||||
|
OLEAutomation,
|
||||||
|
Excel1900,
|
||||||
|
Excel1904,
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,13 +29,16 @@ public sealed partial class TimeDateCalculator
|
|||||||
/// <returns>List of Wox <see cref="Result"/>s.</returns>
|
/// <returns>List of Wox <see cref="Result"/>s.</returns>
|
||||||
public static List<ListItem> ExecuteSearch(SettingsManager settings, string query)
|
public static List<ListItem> ExecuteSearch(SettingsManager settings, string query)
|
||||||
{
|
{
|
||||||
var isEmptySearchInput = string.IsNullOrEmpty(query);
|
var isEmptySearchInput = string.IsNullOrWhiteSpace(query);
|
||||||
List<AvailableResult> availableFormats = new List<AvailableResult>();
|
List<AvailableResult> availableFormats = new List<AvailableResult>();
|
||||||
List<ListItem> results = new List<ListItem>();
|
List<ListItem> results = new List<ListItem>();
|
||||||
|
|
||||||
// currently, all of the search in V2 is keyword search.
|
// currently, all of the search in V2 is keyword search.
|
||||||
var isKeywordSearch = true;
|
var isKeywordSearch = true;
|
||||||
|
|
||||||
|
// Last input parsing error
|
||||||
|
var lastInputParsingErrorMsg = string.Empty;
|
||||||
|
|
||||||
// Switch search type
|
// Switch search type
|
||||||
if (isEmptySearchInput || (!isKeywordSearch && settings.OnlyDateTimeNowGlobal))
|
if (isEmptySearchInput || (!isKeywordSearch && settings.OnlyDateTimeNowGlobal))
|
||||||
{
|
{
|
||||||
@@ -47,13 +50,13 @@ public sealed partial class TimeDateCalculator
|
|||||||
{
|
{
|
||||||
// Search for specified format with specified time/date value
|
// Search for specified format with specified time/date value
|
||||||
var userInput = query.Split(InputDelimiter);
|
var userInput = query.Split(InputDelimiter);
|
||||||
if (TimeAndDateHelper.ParseStringAsDateTime(userInput[1], out DateTime timestamp))
|
if (TimeAndDateHelper.ParseStringAsDateTime(userInput[1], out DateTime timestamp, out lastInputParsingErrorMsg))
|
||||||
{
|
{
|
||||||
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings, null, null, timestamp));
|
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings, null, null, timestamp));
|
||||||
query = userInput[0];
|
query = userInput[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (TimeAndDateHelper.ParseStringAsDateTime(query, out DateTime timestamp))
|
else if (TimeAndDateHelper.ParseStringAsDateTime(query, out DateTime timestamp, out lastInputParsingErrorMsg))
|
||||||
{
|
{
|
||||||
// Return all formats for specified time/date value
|
// Return all formats for specified time/date value
|
||||||
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings, null, null, timestamp));
|
availableFormats.AddRange(AvailableResultsList.GetList(isKeywordSearch, settings, null, null, timestamp));
|
||||||
@@ -88,19 +91,32 @@ public sealed partial class TimeDateCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*htcfreek:Code obsolete with current CmdPal behavior.
|
||||||
// If search term is only a number that can't be parsed return an error message
|
// If search term is only a number that can't be parsed return an error message
|
||||||
if (!isEmptySearchInput && results.Count == 0 && Regex.IsMatch(query, @"\w+\d+.*$") && !query.Any(char.IsWhiteSpace) && (TimeAndDateHelper.IsSpecialInputParsing(query) || !Regex.IsMatch(query, @"\d+[\.:/]\d+")))
|
if (!isEmptySearchInput && results.Count == 0 && Regex.IsMatch(query, @"\w+\d+.*$") && !query.Any(char.IsWhiteSpace) && (TimeAndDateHelper.IsSpecialInputParsing(query) || !Regex.IsMatch(query, @"\d+[\.:/]\d+")))
|
||||||
{
|
{
|
||||||
// Without plugin key word show only if message is not hidden by setting
|
// Without plugin key word show only if message is not hidden by setting
|
||||||
if (!settings.HideNumberMessageOnGlobalQuery)
|
if (!settings.HideNumberMessageOnGlobalQuery)
|
||||||
{
|
{
|
||||||
results.Add(ResultHelper.CreateNumberErrorResult());
|
var er = ResultHelper.CreateInvalidInputErrorResult();
|
||||||
|
if (!string.IsNullOrEmpty(lastInputParsingErrorMsg))
|
||||||
|
{
|
||||||
|
er.Details = new Details() { Body = lastInputParsingErrorMsg };
|
||||||
|
}
|
||||||
|
|
||||||
|
results.Add(er);
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
if (results.Count == 0)
|
if (results.Count == 0)
|
||||||
{
|
{
|
||||||
results.Add(ResultHelper.CreateInvalidInputErrorResult());
|
var er = ResultHelper.CreateInvalidInputErrorResult();
|
||||||
|
if (!string.IsNullOrEmpty(lastInputParsingErrorMsg))
|
||||||
|
{
|
||||||
|
er.Details = new Details() { Body = lastInputParsingErrorMsg };
|
||||||
|
}
|
||||||
|
|
||||||
|
results.Add(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
|||||||
PlaceholderText = Resources.Microsoft_plugin_timedate_placeholder_text;
|
PlaceholderText = Resources.Microsoft_plugin_timedate_placeholder_text;
|
||||||
Id = "com.microsoft.cmdpal.timedate";
|
Id = "com.microsoft.cmdpal.timedate";
|
||||||
_settingsManager = settingsManager;
|
_settingsManager = settingsManager;
|
||||||
|
ShowDetails = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IListItem[] GetItems()
|
public override IListItem[] GetItems()
|
||||||
|
|||||||
@@ -150,6 +150,15 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Days in month.
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_DaysInMonth {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_DaysInMonth", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Era.
|
/// Looks up a localized string similar to Era.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -169,20 +178,38 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
public static string Microsoft_plugin_timedate_ErrorResultSubTitle {
|
public static string Microsoft_plugin_timedate_ErrorConvertCustomFormat {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("Microsoft_plugin_timedate_ErrorResultSubTitle", resourceCulture);
|
return ResourceManager.GetString("Microsoft_plugin_timedate_ErrorConvertCustomFormat", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Error: Invalid number input.
|
/// Looks up a localized string similar to Not a valid Windows file time.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Microsoft_plugin_timedate_ErrorResultTitle {
|
public static string Microsoft_plugin_timedate_ErrorConvertWft {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("Microsoft_plugin_timedate_ErrorResultTitle", resourceCulture);
|
return ResourceManager.GetString("Microsoft_plugin_timedate_ErrorConvertWft", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Excel's 1900 date value.
|
||||||
|
/// </summary>
|
||||||
|
public 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>
|
||||||
|
public static string Microsoft_plugin_timedate_Excel1904 {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_Excel1904", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,11 +232,20 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <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 Invalid custom format:.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static string Microsoft_plugin_timedate_InvalidInput_ErrorMessageSubTitle {
|
public static string Microsoft_plugin_timedate_InvalidCustomFormat {
|
||||||
get {
|
get {
|
||||||
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidInput_ErrorMessageSubTitle", resourceCulture);
|
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidCustomFormat", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Supported input.
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_InvalidInput_DetailsHeader {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidInput_DetailsHeader", resourceCulture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +258,33 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
public 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 A {0}format name{0}, a {0}valid date or time value{0}, or a {0}prefixed number{0}. To search for a format in a specific date/time please use the syntax {0}format::date/time/number{0}.{1}Supported prefixes:{2}'{0}u{0}' for Unix Timestamp{2}'{0}ums{0}' for Unix Timestamp in milliseconds{2}'{0}ft{0}' for Windows file time{2}'{0}oa{0}' for OLE Automation Date{2}'{0}exc{0}' for Excel's 1900 date value{2}'{0}exf{0}' for Excel's 1904 date value.
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_InvalidInput_SupportedInput {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidInput_SupportedInput", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Your input for {0} is outside the range **from {1} to {2}**..
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_InvalidInput_SupportedRange {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_InvalidInput_SupportedRange", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to ISO 8601.
|
/// Looks up a localized string similar to ISO 8601.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -258,6 +321,15 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Leap year.
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_LeapYear {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_LeapYear", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Open.
|
/// Looks up a localized string similar to Open.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -321,6 +393,15 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Not a leap year.
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_NoLeapYear {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_NoLeapYear", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Now.
|
/// Looks up a localized string similar to Now.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -339,6 +420,15 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to OLE Automation Date.
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_OADate {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_OADate", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Search values or type a custom time stamp....
|
/// Looks up a localized string similar to Search values or type a custom time stamp....
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -411,6 +501,42 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Date and time; Time and Date; Custom format.
|
||||||
|
/// </summary>
|
||||||
|
public 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>
|
||||||
|
public 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>
|
||||||
|
public 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>
|
||||||
|
public static string Microsoft_plugin_timedate_SearchTagCustomUtcNow {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_SearchTagCustomUtcNow", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Date.
|
/// Looks up a localized string similar to Date.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -492,6 +618,24 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Custom formats.
|
||||||
|
/// </summary>
|
||||||
|
public 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>
|
||||||
|
public static string Microsoft_plugin_timedate_Setting_CustomFormatsDescription {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_Setting_CustomFormatsDescription", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Use system setting.
|
/// Looks up a localized string similar to Use system setting.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -681,6 +825,15 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to Select for more details..
|
||||||
|
/// </summary>
|
||||||
|
public static string Microsoft_plugin_timedate_show_details {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("Microsoft_plugin_timedate_show_details", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Select or press Ctrl+C to copy.
|
/// Looks up a localized string similar to Select or press Ctrl+C to copy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -155,11 +155,8 @@
|
|||||||
<data name="Microsoft_plugin_timedate_EraAbbreviation" xml:space="preserve">
|
<data name="Microsoft_plugin_timedate_EraAbbreviation" xml:space="preserve">
|
||||||
<value>Era abbreviation</value>
|
<value>Era abbreviation</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Microsoft_plugin_timedate_ErrorResultSubTitle" xml:space="preserve">
|
<data name="Microsoft_plugin_timedate_InvalidInput_DetailsHeader" xml:space="preserve">
|
||||||
<value>Valid prefixes: 'u' for Unix Timestamp, 'ums' for Unix Timestamp in milliseconds, 'ft' for Windows file time</value>
|
<value>Supported input</value>
|
||||||
</data>
|
|
||||||
<data name="Microsoft_plugin_timedate_ErrorResultTitle" xml:space="preserve">
|
|
||||||
<value>Error: Invalid number input</value>
|
|
||||||
</data>
|
</data>
|
||||||
<data name="Microsoft_plugin_timedate_Hour" xml:space="preserve">
|
<data name="Microsoft_plugin_timedate_Hour" xml:space="preserve">
|
||||||
<value>Hour</value>
|
<value>Hour</value>
|
||||||
@@ -372,7 +369,68 @@
|
|||||||
<data name="Microsoft_plugin_timedate_main_page_title" xml:space="preserve">
|
<data name="Microsoft_plugin_timedate_main_page_title" xml:space="preserve">
|
||||||
<value>Time and Date</value>
|
<value>Time and Date</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Microsoft_plugin_timedate_InvalidInput_ErrorMessageSubTitle" xml:space="preserve">
|
<data name="Microsoft_plugin_timedate_InvalidInput_SupportedInput" xml:space="preserve">
|
||||||
<value>Valid prefixes: 'u' for Unix Timestamp, 'ums' for Unix Timestamp in milliseconds, 'ft' for Windows file time</value>
|
<value>A {0}format name{0}, a {0}valid date or time value{0}, or a {0}prefixed number{0}. To search for a format in a specific date/time please use the syntax {0}format::date/time/number{0}.{1}Supported prefixes:{2}'{0}u{0}' for Unix Timestamp{2}'{0}ums{0}' for Unix Timestamp in milliseconds{2}'{0}ft{0}' for Windows file time{2}'{0}oa{0}' for OLE Automation Date{2}'{0}exc{0}' for Excel's 1900 date value{2}'{0}exf{0}' for Excel's 1904 date value</value>
|
||||||
|
<comment>The placed holders are replaced with formatting syntax in code.</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_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_InvalidCustomFormat" xml:space="preserve">
|
||||||
|
<value>Invalid custom format:</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_show_details" xml:space="preserve">
|
||||||
|
<value>Select for more details.</value>
|
||||||
|
</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_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_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_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>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
Reference in New Issue
Block a user