mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-04 10:16:24 +02:00
## Summary of the Pull Request This PR implements two new plugin settings: - **First week of year**  - **First day of week**  ## Detailed Description of the Pull Request / Additional comments For both settings the users can decide to be in sync with the system settings (default) or to use their own setting. The order of days for the `first day of week` setting is based on the current system culture. PT Run respects these settings for the relevant results: - calendar week - week of month - number of day in week
194 lines
7.6 KiB
C#
194 lines
7.6 KiB
C#
// Copyright (c) Microsoft Corporation
|
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
using System;
|
|
using System.Globalization;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text.RegularExpressions;
|
|
|
|
[assembly: InternalsVisibleTo("Microsoft.PowerToys.Run.Plugin.TimeDate.UnitTests")]
|
|
|
|
namespace Microsoft.PowerToys.Run.Plugin.TimeDate.Components
|
|
{
|
|
internal static class TimeAndDateHelper
|
|
{
|
|
/// <summary>
|
|
/// Get the format for the time string
|
|
/// </summary>
|
|
/// <param name="targetFormat">Type of format</param>
|
|
/// <param name="timeLong">Show date with weekday and name of month (long format)</param>
|
|
/// <param name="dateLong">Show time with seconds (long format)</param>
|
|
/// <returns>String that identifies the time/date format (<see href="https://learn.microsoft.com/dotnet/api/system.datetime.tostring"/>)</returns>
|
|
internal static string GetStringFormat(FormatStringType targetFormat, bool timeLong, bool dateLong)
|
|
{
|
|
switch (targetFormat)
|
|
{
|
|
case FormatStringType.Time:
|
|
return timeLong ? "T" : "t";
|
|
case FormatStringType.Date:
|
|
return dateLong ? "D" : "d";
|
|
case FormatStringType.DateTime:
|
|
if (timeLong & dateLong)
|
|
{
|
|
return "F"; // Friday, October 31, 2008 5:04:32 PM
|
|
}
|
|
else if (timeLong & !dateLong)
|
|
{
|
|
return "G"; // 10/31/2008 5:04:32 PM
|
|
}
|
|
else if (!timeLong & dateLong)
|
|
{
|
|
return "f"; // Friday, October 31, 2008 5:04 PM
|
|
}
|
|
else
|
|
{
|
|
// (!timeLong & !dateLong)
|
|
return "g"; // 10/31/2008 5:04 PM
|
|
}
|
|
|
|
default:
|
|
return string.Empty; // Windows default based on current culture settings
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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>
|
|
/// <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
|
|
|
|
while (date.Date.AddDays(1).DayOfWeek != formatSettingFirstDayOfWeek)
|
|
{
|
|
date = date.AddDays(1);
|
|
}
|
|
|
|
return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + adjustment;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the number of the day in the week
|
|
/// </summary>
|
|
/// <param name="date">Date</param>
|
|
/// <returns>Number of the day in the week</returns>
|
|
internal static int GetNumberOfDayInWeek(DateTime date, DayOfWeek formatSettingFirstDayOfWeek)
|
|
{
|
|
int daysInWeek = 7;
|
|
int adjustment = 1; // We count from 1 to 7 and not from 0 to 6
|
|
|
|
return ((date.DayOfWeek + daysInWeek - formatSettingFirstDayOfWeek) % daysInWeek) + adjustment;
|
|
}
|
|
|
|
/// <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>
|
|
/// <returns>True on success, otherwise false</returns>
|
|
internal static bool ParseStringAsDateTime(in string input, out DateTime timestamp)
|
|
{
|
|
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))
|
|
{
|
|
// Unix time stamp
|
|
// We use long instead of int, because int is too small after 03:14:07 UTC 2038-01-19
|
|
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))
|
|
{
|
|
// Unix time stamp in milliseconds
|
|
// We use long instead of int because int is too small after 03:14:07 UTC 2038-01-19
|
|
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(millisecondsUms).LocalDateTime;
|
|
return true;
|
|
}
|
|
else if (Regex.IsMatch(input, @"^ft\d+$") && long.TryParse(input.TrimStart("ft".ToCharArray()), out long secondsFt))
|
|
{
|
|
// Windows file time
|
|
// DateTime.FromFileTime returns as local time.
|
|
timestamp = DateTime.FromFileTime(secondsFt);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
timestamp = new DateTime(1, 1, 1, 1, 1, 1);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test if input is special parsing for Unix time, Unix time in milliseconds or 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");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a CalendarWeekRule enum value based on the plugin setting.
|
|
/// </summary>
|
|
internal static CalendarWeekRule GetCalendarWeekRule(int pluginSetting)
|
|
{
|
|
switch (pluginSetting)
|
|
{
|
|
case 0:
|
|
return CalendarWeekRule.FirstDay;
|
|
case 1:
|
|
return CalendarWeekRule.FirstFullWeek;
|
|
case 2:
|
|
return CalendarWeekRule.FirstFourDayWeek;
|
|
default:
|
|
// Wrong json value and system setting (-1).
|
|
return DateTimeFormatInfo.CurrentInfo.CalendarWeekRule;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a DayOfWeek enum value based on the FirstDayOfWeek plugin setting.
|
|
/// </summary>
|
|
internal static DayOfWeek GetFirstDayOfWeek(int pluginSetting)
|
|
{
|
|
switch (pluginSetting)
|
|
{
|
|
case 0:
|
|
return DayOfWeek.Sunday;
|
|
case 1:
|
|
return DayOfWeek.Monday;
|
|
case 2:
|
|
return DayOfWeek.Tuesday;
|
|
case 3:
|
|
return DayOfWeek.Wednesday;
|
|
case 4:
|
|
return DayOfWeek.Thursday;
|
|
case 5:
|
|
return DayOfWeek.Friday;
|
|
case 6:
|
|
return DayOfWeek.Saturday;
|
|
default:
|
|
// Wrong json value and system setting (-1).
|
|
return DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Type of time/date format
|
|
/// </summary>
|
|
internal enum FormatStringType
|
|
{
|
|
Time,
|
|
Date,
|
|
DateTime,
|
|
}
|
|
}
|