using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.CodeAnalysis;
using SmartFormat.Core.Extensions;
using SmartFormat.Core.Formatting;
using SmartFormat.Core.Parsing;
using SmartFormat.Extensions.Time.Utilities;
using SmartFormat.Utilities;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SmartFormat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright 2011-2024 SmartFormat Project")]
[assembly: AssemblyDescription("This package is a SmartFormat extension for formatting System.DateTime, System.DateTimeOffset and System.TimeSpan types.\r\n\r\nSmartFormat is a lightweight text templating library written in C#.\r\nIt can format various data sources into a string with a minimal, intuitive syntax similar to string.Format.\r\nIt uses extensions to provide named placeholders, localization, pluralization, gender conjugation, and list and time formatting.\r\n ")]
[assembly: AssemblyFileVersion("3.5.0.886")]
[assembly: AssemblyInformationalVersion("3.5.0+c097ea6fc668033580909317ed90679dacbb0e8a")]
[assembly: AssemblyProduct("SmartFormat")]
[assembly: AssemblyTitle("SmartFormat.Extensions.Time")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/axuno/SmartFormat.git")]
[assembly: AssemblyVersion("3.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace SmartFormat.Extensions
{
public class TimeFormatter : IFormatter
{
private string _fallbackLanguage = "en";
[Obsolete("Use property \"Name\" instead", true)]
public string[] Names { get; set; } = new string[3]
{
"timespan",
"time",
string.Empty
};
public string Name { get; set; } = "time";
public bool CanAutoDetect { get; set; } = true;
public TimeSpanFormatOptions DefaultFormatOptions { get; set; }
public string FallbackLanguage
{
get
{
return _fallbackLanguage;
}
set
{
if (value == string.Empty)
{
_fallbackLanguage = value;
return;
}
if (CommonLanguagesTimeTextInfo.GetTimeTextInfo(value) != null)
{
_fallbackLanguage = value;
return;
}
throw new ArgumentException("No TimeTextInfo found for language '" + value + "'.");
}
}
[Obsolete("This property is not supported any more. Changed process to get or set the default culture.", true)]
public string DefaultTwoLetterISOLanguageName { get; set; } = "en";
public TimeFormatter()
{
DefaultFormatOptions = TimeSpanUtility.DefaultFormatOptions;
}
[Obsolete("This constructor is not required. Changed process to determine the default culture.", true)]
public TimeFormatter(string defaultTwoLetterLanguageName)
{
if (CommonLanguagesTimeTextInfo.GetTimeTextInfo(defaultTwoLetterLanguageName) == null)
{
throw new ArgumentException("Language '" + defaultTwoLetterLanguageName + "' for defaultTwoLetterLanguageName is not implemented.");
}
DefaultTwoLetterISOLanguageName = defaultTwoLetterLanguageName;
DefaultFormatOptions = TimeSpanUtility.DefaultFormatOptions;
}
public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
{
Format format = formattingInfo.Format;
Placeholder placeholder = formattingInfo.Placeholder;
string text = ((placeholder != null) ? placeholder.FormatterName : null) ?? string.Empty;
object currentValue = formattingInfo.CurrentValue;
if (format != null && format.HasNested)
{
if (text == string.Empty)
{
return false;
}
throw new FormatException("Formatter named '" + text + "' cannot handle nested formats.");
}
string text2 = formattingInfo.FormatterOptions.Trim();
string text3 = ((format != null) ? ((FormatItem)format).RawText.Trim() : null) ?? string.Empty;
if (text == string.Empty && text2 == string.Empty && text3 == string.Empty)
{
return false;
}
bool flag = text2 != string.Empty && text3 == string.Empty;
string formattingOptions = (flag ? text2 : text3);
TimeSpan? fromTime = GetFromTime(currentValue, formattingOptions);
if (!fromTime.HasValue)
{
if (text == string.Empty)
{
return false;
}
throw new FormatException("Formatter named '" + text + "' can only process types of TimeSpan, DateTime, DateTimeOffset");
}
TimeTextInfo timeTextInfo = GetTimeTextInfo(formattingInfo, flag);
TimeSpanFormatOptions options = TimeSpanFormatOptionsConverter.Parse(flag ? text2 : text3);
string text4 = fromTime.Value.ToTimeString(options, timeTextInfo);
formattingInfo.Write(text4);
return true;
}
private static TimeSpan? GetFromTime(object? current, string? formattingOptions)
{
TimeSpan? result = null;
if (!(current is TimeSpan value))
{
if (!(current is DateTime dateTime))
{
if (current is DateTimeOffset dateTimeOffset && formattingOptions != string.Empty)
{
result = SystemTime.OffsetNow().UtcDateTime.Subtract(dateTimeOffset.UtcDateTime);
}
}
else if (formattingOptions != string.Empty)
{
result = SystemTime.Now().ToUniversalTime().Subtract(dateTime.ToUniversalTime());
}
}
else
{
result = value;
}
return result;
}
private TimeTextInfo GetTimeTextInfo(IFormattingInfo formattingInfo, bool v2Compatibility)
{
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
if (formattingInfo.FormatDetails.Provider?.GetFormat(typeof(TimeTextInfo)) is TimeTextInfo result)
{
return result;
}
TimeTextInfo timeTextInfo = CommonLanguagesTimeTextInfo.GetTimeTextInfo(GetCultureInfo(formattingInfo, v2Compatibility).TwoLetterISOLanguageName);
if (timeTextInfo != null)
{
return timeTextInfo;
}
if (FallbackLanguage == string.Empty)
{
throw new FormattingException((FormatItem)(object)formattingInfo.Placeholder, "TimeTextInfo could not be found for the given culture argument '" + formattingInfo.FormatterOptions + "'.", 0);
}
if (FallbackLanguage != string.Empty)
{
return CommonLanguagesTimeTextInfo.GetTimeTextInfo(FallbackLanguage);
}
throw new ArgumentException("TimeTextInfo could not be found for the given IFormatProvider.", "formattingInfo");
}
private static CultureInfo GetCultureInfo(IFormattingInfo formattingInfo, bool v2Compatibility)
{
string text = ((!v2Compatibility) ? formattingInfo.FormatterOptions.Trim() : string.Empty);
if (text == string.Empty)
{
if (formattingInfo.FormatDetails.Provider is CultureInfo result)
{
return result;
}
return CultureInfo.CurrentUICulture;
}
return CultureInfo.GetCultureInfo(text);
}
}
}
namespace SmartFormat.Extensions.Time.Utilities
{
public static class CommonLanguagesTimeTextInfo
{
private static readonly Dictionary<string, TimeTextInfo> _customLanguage = new Dictionary<string, TimeTextInfo>();
public static TimeTextInfo English
{
get
{
TimeTextInfo timeTextInfo = new TimeTextInfo();
timeTextInfo.PluralRule = PluralRules.GetPluralRule("en");
timeTextInfo.Ptxt_week = new string[2] { "{0} week", "{0} weeks" };
timeTextInfo.Ptxt_day = new string[2] { "{0} day", "{0} days" };
timeTextInfo.Ptxt_hour = new string[2] { "{0} hour", "{0} hours" };
timeTextInfo.Ptxt_minute = new string[2] { "{0} minute", "{0} minutes" };
timeTextInfo.Ptxt_second = new string[2] { "{0} second", "{0} seconds" };
timeTextInfo.Ptxt_millisecond = new string[2] { "{0} millisecond", "{0} milliseconds" };
timeTextInfo.Ptxt_w = new string[1] { "{0}w" };
timeTextInfo.Ptxt_d = new string[1] { "{0}d" };
timeTextInfo.Ptxt_h = new string[1] { "{0}h" };
timeTextInfo.Ptxt_m = new string[1] { "{0}m" };
timeTextInfo.Ptxt_s = new string[1] { "{0}s" };
timeTextInfo.Ptxt_ms = new string[1] { "{0}ms" };
timeTextInfo.Ptxt_lessThan = "less than {0}";
return timeTextInfo;
}
}
public static TimeTextInfo French
{
get
{
TimeTextInfo timeTextInfo = new TimeTextInfo();
timeTextInfo.PluralRule = PluralRules.GetPluralRule("fr");
timeTextInfo.Ptxt_week = new string[2] { "{0} semaine", "{0} semaines" };
timeTextInfo.Ptxt_day = new string[2] { "{0} jour", "{0} jours" };
timeTextInfo.Ptxt_hour = new string[2] { "{0} heure", "{0} heures" };
timeTextInfo.Ptxt_minute = new string[2] { "{0} minute", "{0} minutes" };
timeTextInfo.Ptxt_second = new string[2] { "{0} seconde", "{0} secondes" };
timeTextInfo.Ptxt_millisecond = new string[2] { "{0} milliseconde", "{0} millisecondes" };
timeTextInfo.Ptxt_w = new string[1] { "{0}sem" };
timeTextInfo.Ptxt_d = new string[1] { "{0}j" };
timeTextInfo.Ptxt_h = new string[1] { "{0}h" };
timeTextInfo.Ptxt_m = new string[1] { "{0}m" };
timeTextInfo.Ptxt_s = new string[1] { "{0}s" };
timeTextInfo.Ptxt_ms = new string[1] { "{0}ms" };
timeTextInfo.Ptxt_lessThan = "moins que {0}";
return timeTextInfo;
}
}
public static TimeTextInfo Spanish
{
get
{
TimeTextInfo timeTextInfo = new TimeTextInfo();
timeTextInfo.PluralRule = PluralRules.GetPluralRule("es");
timeTextInfo.Ptxt_week = new string[2] { "{0} semana", "{0} semanas" };
timeTextInfo.Ptxt_day = new string[2] { "{0} día", "{0} días" };
timeTextInfo.Ptxt_hour = new string[2] { "{0} hore", "{0} horas" };
timeTextInfo.Ptxt_minute = new string[2] { "{0} minuto", "{0} minutos" };
timeTextInfo.Ptxt_second = new string[2] { "{0} segundo", "{0} segundos" };
timeTextInfo.Ptxt_millisecond = new string[2] { "{0} milisegundo", "{0} milisegundos" };
timeTextInfo.Ptxt_w = new string[1] { "{0}sem" };
timeTextInfo.Ptxt_d = new string[1] { "{0}d" };
timeTextInfo.Ptxt_h = new string[1] { "{0}h" };
timeTextInfo.Ptxt_m = new string[1] { "{0}m" };
timeTextInfo.Ptxt_s = new string[1] { "{0}s" };
timeTextInfo.Ptxt_ms = new string[1] { "{0}ms" };
timeTextInfo.Ptxt_lessThan = "menos que {0}";
return timeTextInfo;
}
}
public static TimeTextInfo Portuguese
{
get
{
TimeTextInfo timeTextInfo = new TimeTextInfo();
timeTextInfo.PluralRule = PluralRules.GetPluralRule("pt");
timeTextInfo.Ptxt_week = new string[2] { "{0} semana", "{0} semanas" };
timeTextInfo.Ptxt_day = new string[2] { "{0} dia", "{0} dias" };
timeTextInfo.Ptxt_hour = new string[2] { "{0} hora", "{0} horas" };
timeTextInfo.Ptxt_minute = new string[2] { "{0} minuto", "{0} minutos" };
timeTextInfo.Ptxt_second = new string[2] { "{0} segundo", "{0} segundos" };
timeTextInfo.Ptxt_millisecond = new string[2] { "{0} milissegundo", "{0} milissegundos" };
timeTextInfo.Ptxt_w = new string[1] { "{0}sem" };
timeTextInfo.Ptxt_d = new string[1] { "{0}d" };
timeTextInfo.Ptxt_h = new string[1] { "{0}h" };
timeTextInfo.Ptxt_m = new string[1] { "{0}m" };
timeTextInfo.Ptxt_s = new string[1] { "{0}s" };
timeTextInfo.Ptxt_ms = new string[1] { "{0}ms" };
timeTextInfo.Ptxt_lessThan = "menos do que {0}";
return timeTextInfo;
}
}
public static TimeTextInfo Italian
{
get
{
TimeTextInfo timeTextInfo = new TimeTextInfo();
timeTextInfo.PluralRule = PluralRules.GetPluralRule("it");
timeTextInfo.Ptxt_week = new string[2] { "{0} settimana", "{0} settimane" };
timeTextInfo.Ptxt_day = new string[2] { "{0} giorno", "{0} giorni" };
timeTextInfo.Ptxt_hour = new string[2] { "{0} ora", "{0} ore" };
timeTextInfo.Ptxt_minute = new string[2] { "{0} minuto", "{0} minuti" };
timeTextInfo.Ptxt_second = new string[2] { "{0} secondo", "{0} secondi" };
timeTextInfo.Ptxt_millisecond = new string[2] { "{0} millisecondo", "{0} millisecondi" };
timeTextInfo.Ptxt_w = new string[1] { "{0}set" };
timeTextInfo.Ptxt_d = new string[1] { "{0}g" };
timeTextInfo.Ptxt_h = new string[1] { "{0}h" };
timeTextInfo.Ptxt_m = new string[1] { "{0}m" };
timeTextInfo.Ptxt_s = new string[1] { "{0}s" };
timeTextInfo.Ptxt_ms = new string[1] { "{0}ms" };
timeTextInfo.Ptxt_lessThan = "meno di {0}";
return timeTextInfo;
}
}
public static TimeTextInfo German
{
get
{
TimeTextInfo timeTextInfo = new TimeTextInfo();
timeTextInfo.PluralRule = PluralRules.GetPluralRule("de");
timeTextInfo.Ptxt_week = new string[2] { "{0} Woche", "{0} Wochen" };
timeTextInfo.Ptxt_day = new string[2] { "{0} Tag", "{0} Tage" };
timeTextInfo.Ptxt_hour = new string[2] { "{0} Stunde", "{0} Stunden" };
timeTextInfo.Ptxt_minute = new string[2] { "{0} Minute", "{0} Minuten" };
timeTextInfo.Ptxt_second = new string[2] { "{0} Sekunde", "{0} Sekunden" };
timeTextInfo.Ptxt_millisecond = new string[2] { "{0} Millisekunde", "{0} Millisekunden" };
timeTextInfo.Ptxt_w = new string[1] { "{0}w" };
timeTextInfo.Ptxt_d = new string[1] { "{0}t" };
timeTextInfo.Ptxt_h = new string[1] { "{0}h" };
timeTextInfo.Ptxt_m = new string[1] { "{0}m" };
timeTextInfo.Ptxt_s = new string[1] { "{0}s" };
timeTextInfo.Ptxt_ms = new string[1] { "{0}ms" };
timeTextInfo.Ptxt_lessThan = "weniger als {0}";
return timeTextInfo;
}
}
public static void AddLanguage(string twoLetterIsoLanguageName, TimeTextInfo timeTextInfo)
{
string key = twoLetterIsoLanguageName.ToLower();
_customLanguage.Add(key, timeTextInfo);
}
public static TimeTextInfo? GetTimeTextInfo(string twoLetterIsoLanguageName)
{
if (_customLanguage.TryGetValue(twoLetterIsoLanguageName, out TimeTextInfo value))
{
return value;
}
return twoLetterIsoLanguageName switch
{
"en" => English,
"fr" => French,
"es" => Spanish,
"pt" => Portuguese,
"it" => Italian,
"de" => German,
_ => null,
};
}
}
[Flags]
public enum TimeSpanFormatOptions
{
None = 0,
Abbreviate = 1,
AbbreviateOff = 2,
LessThan = 4,
LessThanOff = 8,
TruncateShortest = 0x10,
TruncateAuto = 0x20,
TruncateFill = 0x40,
TruncateFull = 0x80,
RangeMilliSeconds = 0x100,
RangeSeconds = 0x200,
RangeMinutes = 0x400,
RangeHours = 0x800,
RangeDays = 0x1000,
RangeWeeks = 0x2000
}
internal static class TimeSpanFormatOptionsPresets
{
public const TimeSpanFormatOptions Abbreviate = TimeSpanFormatOptions.Abbreviate | TimeSpanFormatOptions.AbbreviateOff;
public const TimeSpanFormatOptions LessThan = TimeSpanFormatOptions.LessThan | TimeSpanFormatOptions.LessThanOff;
public const TimeSpanFormatOptions Truncate = TimeSpanFormatOptions.TruncateShortest | TimeSpanFormatOptions.TruncateAuto | TimeSpanFormatOptions.TruncateFill | TimeSpanFormatOptions.TruncateFull;
public const TimeSpanFormatOptions Range = TimeSpanFormatOptions.RangeMilliSeconds | TimeSpanFormatOptions.RangeSeconds | TimeSpanFormatOptions.RangeMinutes | TimeSpanFormatOptions.RangeHours | TimeSpanFormatOptions.RangeDays | TimeSpanFormatOptions.RangeWeeks;
}
internal static class TimeSpanFormatOptionsConverter
{
private static readonly Regex parser = new Regex("\\b(w|week|weeks|d|day|days|h|hour|hours|m|minute|minutes|s|second|seconds|ms|millisecond|milliseconds|auto|short|fill|full|abbr|noabbr|less|noless)\\b", RegexOptions.IgnoreCase | RegexOptions.Compiled, TimeSpan.FromMilliseconds(500.0));
public static TimeSpanFormatOptions Merge(this TimeSpanFormatOptions left, TimeSpanFormatOptions right)
{
TimeSpanFormatOptions[] array = new TimeSpanFormatOptions[4]
{
TimeSpanFormatOptions.Abbreviate | TimeSpanFormatOptions.AbbreviateOff,
TimeSpanFormatOptions.LessThan | TimeSpanFormatOptions.LessThanOff,
TimeSpanFormatOptions.RangeMilliSeconds | TimeSpanFormatOptions.RangeSeconds | TimeSpanFormatOptions.RangeMinutes | TimeSpanFormatOptions.RangeHours | TimeSpanFormatOptions.RangeDays | TimeSpanFormatOptions.RangeWeeks,
TimeSpanFormatOptions.TruncateShortest | TimeSpanFormatOptions.TruncateAuto | TimeSpanFormatOptions.TruncateFill | TimeSpanFormatOptions.TruncateFull
};
foreach (TimeSpanFormatOptions timeSpanFormatOptions in array)
{
if ((left & timeSpanFormatOptions) == 0)
{
left |= right & timeSpanFormatOptions;
}
}
return left;
}
public static TimeSpanFormatOptions Mask(this TimeSpanFormatOptions timeSpanFormatOptions, TimeSpanFormatOptions mask)
{
return timeSpanFormatOptions & mask;
}
public static IEnumerable<TimeSpanFormatOptions> AllFlags(this TimeSpanFormatOptions timeSpanFormatOptions)
{
for (uint value = 1u; value <= (uint)timeSpanFormatOptions; value <<= 1)
{
if ((value & (uint)timeSpanFormatOptions) != 0)
{
yield return (TimeSpanFormatOptions)value;
}
}
}
public static TimeSpanFormatOptions Parse(string formatString)
{
formatString = formatString.ToLower();
TimeSpanFormatOptions timeSpanFormatOptions = TimeSpanFormatOptions.None;
IEnumerator enumerator = parser.Matches(formatString).GetEnumerator();
try
{
while (enumerator.MoveNext())
{
switch (((Match)enumerator.Current).Value)
{
case "w":
case "week":
case "weeks":
timeSpanFormatOptions |= TimeSpanFormatOptions.RangeWeeks;
break;
case "d":
case "days":
case "day":
timeSpanFormatOptions |= TimeSpanFormatOptions.RangeDays;
break;
case "h":
case "hour":
case "hours":
timeSpanFormatOptions |= TimeSpanFormatOptions.RangeHours;
break;
case "m":
case "minute":
case "minutes":
timeSpanFormatOptions |= TimeSpanFormatOptions.RangeMinutes;
break;
case "s":
case "second":
case "seconds":
timeSpanFormatOptions |= TimeSpanFormatOptions.RangeSeconds;
break;
case "ms":
case "millisecond":
case "milliseconds":
timeSpanFormatOptions |= TimeSpanFormatOptions.RangeMilliSeconds;
break;
case "short":
timeSpanFormatOptions |= TimeSpanFormatOptions.TruncateShortest;
break;
case "auto":
timeSpanFormatOptions |= TimeSpanFormatOptions.TruncateAuto;
break;
case "fill":
timeSpanFormatOptions |= TimeSpanFormatOptions.TruncateFill;
break;
case "full":
timeSpanFormatOptions |= TimeSpanFormatOptions.TruncateFull;
break;
case "abbr":
timeSpanFormatOptions |= TimeSpanFormatOptions.Abbreviate;
break;
case "noabbr":
timeSpanFormatOptions |= TimeSpanFormatOptions.AbbreviateOff;
break;
case "less":
timeSpanFormatOptions |= TimeSpanFormatOptions.LessThan;
break;
case "noless":
timeSpanFormatOptions |= TimeSpanFormatOptions.LessThanOff;
break;
}
}
return timeSpanFormatOptions;
}
finally
{
IDisposable disposable = enumerator as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
}
}
public static class TimeSpanUtility
{
private static TimeSpanFormatOptions _rangeMin;
private static TimeSpanFormatOptions _truncate;
private static bool _lessThan;
private static bool _abbreviate;
private static Func<double, double>? _round;
private static TimeTextInfo? _timeTextInfo;
public static TimeSpanFormatOptions DefaultFormatOptions { get; set; }
public static TimeSpanFormatOptions AbsoluteDefaults { get; }
static TimeSpanUtility()
{
DefaultFormatOptions = TimeSpanFormatOptions.AbbreviateOff | TimeSpanFormatOptions.LessThan | TimeSpanFormatOptions.TruncateAuto | TimeSpanFormatOptions.RangeSeconds | TimeSpanFormatOptions.RangeDays;
AbsoluteDefaults = DefaultFormatOptions;
}
public static string ToTimeString(this TimeSpan fromTime, TimeSpanFormatOptions options, TimeTextInfo timeTextInfo)
{
options = options.Merge(DefaultFormatOptions).Merge(AbsoluteDefaults);
TimeSpanFormatOptions timeSpanFormatOptions = options.Mask(TimeSpanFormatOptions.RangeMilliSeconds | TimeSpanFormatOptions.RangeSeconds | TimeSpanFormatOptions.RangeMinutes | TimeSpanFormatOptions.RangeHours | TimeSpanFormatOptions.RangeDays | TimeSpanFormatOptions.RangeWeeks).AllFlags().Last();
_rangeMin = options.Mask(TimeSpanFormatOptions.RangeMilliSeconds | TimeSpanFormatOptions.RangeSeconds | TimeSpanFormatOptions.RangeMinutes | TimeSpanFormatOptions.RangeHours | TimeSpanFormatOptions.RangeDays | TimeSpanFormatOptions.RangeWeeks).AllFlags().First();
_truncate = options.Mask(TimeSpanFormatOptions.TruncateShortest | TimeSpanFormatOptions.TruncateAuto | TimeSpanFormatOptions.TruncateFill | TimeSpanFormatOptions.TruncateFull).AllFlags().First();
_lessThan = options.Mask(TimeSpanFormatOptions.LessThan | TimeSpanFormatOptions.LessThanOff) != TimeSpanFormatOptions.LessThanOff;
_abbreviate = options.Mask(TimeSpanFormatOptions.Abbreviate | TimeSpanFormatOptions.AbbreviateOff) != TimeSpanFormatOptions.AbbreviateOff;
_round = (_lessThan ? new Func<double, double>(Math.Floor) : new Func<double, double>(Math.Ceiling));
_timeTextInfo = timeTextInfo;
switch (_rangeMin)
{
case TimeSpanFormatOptions.RangeWeeks:
fromTime = TimeSpan.FromDays(_round(fromTime.TotalDays / 7.0) * 7.0);
break;
case TimeSpanFormatOptions.RangeDays:
fromTime = TimeSpan.FromDays(_round(fromTime.TotalDays));
break;
case TimeSpanFormatOptions.RangeHours:
fromTime = TimeSpan.FromHours(_round(fromTime.TotalHours));
break;
case TimeSpanFormatOptions.RangeMinutes:
fromTime = TimeSpan.FromMinutes(_round(fromTime.TotalMinutes));
break;
case TimeSpanFormatOptions.RangeSeconds:
fromTime = TimeSpan.FromSeconds(_round(fromTime.TotalSeconds));
break;
case TimeSpanFormatOptions.RangeMilliSeconds:
fromTime = TimeSpan.FromMilliseconds(_round(fromTime.TotalMilliseconds));
break;
}
bool flag = false;
StringBuilder stringBuilder = new StringBuilder();
for (TimeSpanFormatOptions timeSpanFormatOptions2 = timeSpanFormatOptions; timeSpanFormatOptions2 >= _rangeMin; timeSpanFormatOptions2 = (TimeSpanFormatOptions)((int)timeSpanFormatOptions2 >> 1))
{
int num;
if (timeSpanFormatOptions2 <= TimeSpanFormatOptions.RangeMinutes)
{
if (timeSpanFormatOptions2 != TimeSpanFormatOptions.RangeMilliSeconds)
{
if (timeSpanFormatOptions2 != TimeSpanFormatOptions.RangeSeconds)
{
if (timeSpanFormatOptions2 != TimeSpanFormatOptions.RangeMinutes)
{
continue;
}
num = (int)Math.Floor(fromTime.TotalMinutes);
fromTime -= TimeSpan.FromMinutes(num);
}
else
{
num = (int)Math.Floor(fromTime.TotalSeconds);
fromTime -= TimeSpan.FromSeconds(num);
}
}
else
{
num = (int)Math.Floor(fromTime.TotalMilliseconds);
fromTime -= TimeSpan.FromMilliseconds(num);
}
}
else if (timeSpanFormatOptions2 != TimeSpanFormatOptions.RangeHours)
{
if (timeSpanFormatOptions2 != TimeSpanFormatOptions.RangeDays)
{
if (timeSpanFormatOptions2 != TimeSpanFormatOptions.RangeWeeks)
{
continue;
}
num = (int)Math.Floor(fromTime.TotalDays / 7.0);
fromTime -= TimeSpan.FromDays(num * 7);
}
else
{
num = (int)Math.Floor(fromTime.TotalDays);
fromTime -= TimeSpan.FromDays(num);
}
}
else
{
num = (int)Math.Floor(fromTime.TotalHours);
fromTime -= TimeSpan.FromHours(num);
}
if (!ShouldTruncate(num, flag, out var displayThisValue))
{
continue;
}
PrepareOutput(num, timeSpanFormatOptions2 == _rangeMin, flag, stringBuilder, ref displayThisValue);
if (displayThisValue)
{
if (flag)
{
stringBuilder.Append(' ');
}
string unitText = _timeTextInfo.GetUnitText(timeSpanFormatOptions2, num, _abbreviate);
stringBuilder.Append(unitText);
flag = true;
}
}
return stringBuilder.ToString();
}
private static bool ShouldTruncate(int value, bool textStarted, out bool displayThisValue)
{
displayThisValue = false;
switch (_truncate)
{
case TimeSpanFormatOptions.TruncateShortest:
if (textStarted)
{
return false;
}
if (value > 0)
{
displayThisValue = true;
}
return true;
case TimeSpanFormatOptions.TruncateAuto:
if (value > 0)
{
displayThisValue = true;
}
return true;
case TimeSpanFormatOptions.TruncateFill:
if (textStarted || value > 0)
{
displayThisValue = true;
}
return true;
case TimeSpanFormatOptions.TruncateFull:
displayThisValue = true;
return true;
default:
return false;
}
}
private static void PrepareOutput(int value, bool isRangeMin, bool hasTextStarted, StringBuilder result, ref bool displayThisValue)
{
if (isRangeMin && !hasTextStarted)
{
displayThisValue = true;
if (_lessThan && value < 1)
{
string unitText = _timeTextInfo.GetUnitText(_rangeMin, 1, _abbreviate);
result.Append(_timeTextInfo.GetLessThanText(unitText));
displayThisValue = false;
}
}
}
public static TimeSpan Round(this TimeSpan fromTime, long intervalTicks)
{
long num = fromTime.Ticks % intervalTicks;
if (num >= intervalTicks >> 1)
{
num -= intervalTicks;
}
return TimeSpan.FromTicks(fromTime.Ticks - num);
}
}
public class TimeTextInfo
{
public PluralRuleDelegate? PluralRule { get; set; }
public string[] Ptxt_d { get; set; } = Array.Empty<string>();
public string[] Ptxt_day { get; set; } = Array.Empty<string>();
public string[] Ptxt_h { get; set; } = Array.Empty<string>();
public string[] Ptxt_hour { get; set; } = Array.Empty<string>();
public string Ptxt_lessThan { get; set; } = string.Empty;
public string[] Ptxt_m { get; set; } = Array.Empty<string>();
public string[] Ptxt_millisecond { get; set; } = Array.Empty<string>();
public string[] Ptxt_minute { get; set; } = Array.Empty<string>();
public string[] Ptxt_ms { get; set; } = Array.Empty<string>();
public string[] Ptxt_s { get; set; } = Array.Empty<string>();
public string[] Ptxt_second { get; set; } = Array.Empty<string>();
public string[] Ptxt_w { get; set; } = Array.Empty<string>();
public string[] Ptxt_week { get; set; } = Array.Empty<string>();
private static string GetValue(PluralRuleDelegate pluralRule, int value, IReadOnlyList<string> units)
{
int index = ((units.Count != 1) ? pluralRule.Invoke((decimal)value, units.Count) : 0);
return string.Format(units[index], value);
}
public virtual string GetLessThanText(string minimumValue)
{
return string.Format(Ptxt_lessThan, minimumValue);
}
public virtual string GetUnitText(TimeSpanFormatOptions unit, int value, bool abbr)
{
if (PluralRule == null)
{
throw new InvalidOperationException("Plural rule delegate must not be null");
}
return unit switch
{
TimeSpanFormatOptions.RangeWeeks => GetValue(PluralRule, value, abbr ? Ptxt_w : Ptxt_week),
TimeSpanFormatOptions.RangeDays => GetValue(PluralRule, value, abbr ? Ptxt_d : Ptxt_day),
TimeSpanFormatOptions.RangeHours => GetValue(PluralRule, value, abbr ? Ptxt_h : Ptxt_hour),
TimeSpanFormatOptions.RangeMinutes => GetValue(PluralRule, value, abbr ? Ptxt_m : Ptxt_minute),
TimeSpanFormatOptions.RangeSeconds => GetValue(PluralRule, value, abbr ? Ptxt_s : Ptxt_second),
TimeSpanFormatOptions.RangeMilliSeconds => GetValue(PluralRule, value, abbr ? Ptxt_ms : Ptxt_millisecond),
_ => string.Empty,
};
}
}
}