// 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)
{
DateTime beginningOfMonth = new DateTime(date.Year, date.Month, 1);
while (date.Date.AddDays(1).DayOfWeek != CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
{
date = date.AddDays(1);
}
return (int)Math.Truncate((double)date.Subtract(beginningOfMonth).TotalDays / 7f) + 1;
}
///
/// Returns the number of the day in the week
///
/// Date
/// Number of the day in the week
internal static int GetNumberOfDayInWeek(DateTime date)
{
int daysInWeek = 7;
int adjustment = 1; // We count from 1 to 7 and not from 0 to 6
int formatSettingFirstDayOfWeek = (int)CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
return ((int)(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");
}
}
///
/// Type of time/date format
///
internal enum FormatStringType
{
Time,
Date,
DateTime,
}
}