// 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 { /// /// Get the format for the time string /// /// Type of format /// Show date with weekday and name of month (long format) /// Show time with seconds (long format) /// String that identifies the time/date format () 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 } } /// /// Returns the number week in the month (Used code from 'David Morton' from ) /// /// date /// Number of week in the month 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; } /// /// Returns the number of the day in the week /// /// Date /// Number of the day in the week 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; } /// /// Convert input string to a object in local time /// /// String with date/time /// The new object /// True on success, otherwise false 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; } } /// /// Test if input is special parsing for Unix time, Unix time in milliseconds or File time. /// /// String with date/time /// True if yes, otherwise false internal static bool IsSpecialInputParsing(string input) { return Regex.IsMatch(input, @"^.*(u|ums|ft)\d"); } /// /// Returns a CalendarWeekRule enum value based on the plugin setting. /// 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; } } /// /// Returns a DayOfWeek enum value based on the FirstDayOfWeek plugin setting. /// 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; } } } /// /// Type of time/date format /// internal enum FormatStringType { Time, Date, DateTime, } }