Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SmartFormat Extensions Time v3.6.100
BepInEx/core/SmartFormat.Extensions.Time/netstandard2.1/SmartFormat.Extensions.Time.dll
Decompiled 6 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.Json; 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-2025 SmartFormat Project")] [assembly: AssemblyDescription("This package is a SmartFormat extension for formatting System.DateTime, System.DateTimeOffset and System.TimeSpan types.\n\nSmartFormat is a lightweight text templating library written in C#.\nIt can format various data sources into a string with a minimal, intuitive syntax similar to string.Format.\nIt uses extensions to provide named placeholders, localization, pluralization, gender conjugation, and list and time formatting.\n ")] [assembly: AssemblyFileVersion("3.6.1")] [assembly: AssemblyInformationalVersion("3.6.1+ebf693558e4e511ae8542bdca527d55077296c4d")] [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)] [ExcludeFromCodeCoverage] public string[] Names { get; set; } = new string[3] { "timespan", "time", string.Empty }; public string Name { get; set; } = "time"; public bool CanAutoDetect { get; set; } 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)] [ExcludeFromCodeCoverage] 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)] [ExcludeFromCodeCoverage] 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) { //IL_0088: Unknown result type (might be due to invalid IL or missing references) Format format = formattingInfo.Format; Placeholder placeholder = formattingInfo.Placeholder; if (string.IsNullOrEmpty((placeholder != null) ? placeholder.FormatterName : null)) { return false; } object currentValue = formattingInfo.CurrentValue; if ((!(currentValue is TimeSpan) && !(currentValue is DateTime) && !(currentValue is DateTimeOffset)) || 1 == 0) { Format format2 = formattingInfo.Format; throw new FormattingException((format2 != null) ? format2.Items.FirstOrDefault() : null, "'TimeFormatter' can only process types of TimeSpan, DateTime, DateTimeOffset, " + $"but not '{formattingInfo.CurrentValue?.GetType()}'", 0); } IList<string> timeParts = GetTimeParts(formattingInfo); if (timeParts == null) { return false; } if (format != null && ((FormatItem)format).Length > 1 && format.HasNested) { format.Items.RemoveAt(0); formattingInfo.FormatAsChild(format, (object)timeParts); return true; } formattingInfo.Write(string.Join(" ", timeParts)); return true; } private IList<string>? GetTimeParts(IFormattingInfo formattingInfo) { Format format = formattingInfo.Format; object currentValue = formattingInfo.CurrentValue; string text = formattingInfo.FormatterOptions.Trim(); string text2 = ((format != null) ? ((FormatItem)format).RawText.Trim() : null) ?? string.Empty; bool flag = text != string.Empty && text2 == string.Empty; string formatString = (flag ? text : text2); TimeSpan? fromTime = GetFromTime(currentValue); if (!fromTime.HasValue) { return null; } TimeTextInfo timeTextInfo = GetTimeTextInfo(formattingInfo, flag); TimeSpanFormatOptions options = TimeSpanFormatOptionsConverter.Parse(formatString); return fromTime.Value.ToTimeParts(options, timeTextInfo); } private static TimeSpan? GetFromTime(object? current) { TimeSpan? result = null; if (!(current is TimeSpan value)) { if (!(current is DateTime dateTime)) { if (current is DateTimeOffset dateTimeOffset) { result = SystemTime.OffsetNow().UtcDateTime.Subtract(dateTimeOffset.UtcDateTime); } } else { 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>(); [Obsolete("Use GetTimeTextInfo(\"en\") instead")] [ExcludeFromCodeCoverage] public static TimeTextInfo English => GetTimeTextInfo("en"); [Obsolete("Use GetTimeTextInfo(\"fr\") instead")] [ExcludeFromCodeCoverage] public static TimeTextInfo French => GetTimeTextInfo("fr"); [Obsolete("Use GetTimeTextInfo(\"es\") instead")] [ExcludeFromCodeCoverage] public static TimeTextInfo Spanish => GetTimeTextInfo("es"); [Obsolete("Use GetTimeTextInfo(\"pt\") instead")] [ExcludeFromCodeCoverage] public static TimeTextInfo Portuguese => GetTimeTextInfo("pt"); [Obsolete("Use GetTimeTextInfo(\"it\") instead")] [ExcludeFromCodeCoverage] public static TimeTextInfo Italian => GetTimeTextInfo("it"); [Obsolete("Use GetTimeTextInfo(\"de\") instead")] [ExcludeFromCodeCoverage] public static TimeTextInfo German => GetTimeTextInfo("de"); 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; } value = LoadTimeTextInfo(twoLetterIsoLanguageName); if (value == null) { return null; } _customLanguage.Add(twoLetterIsoLanguageName, value); return value; } private static TimeTextInfo? LoadTimeTextInfo(string languageCode) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = "SmartFormat.Extensions.Time.Resources." + languageCode + ".json"; using Stream stream = executingAssembly.GetManifestResourceStream(name); if (stream == null) { return null; } using StreamReader streamReader = new StreamReader(stream); TimeTextInfoData timeTextInfoData = JsonSerializer.Deserialize<TimeTextInfoData>(streamReader.ReadToEnd()); return new TimeTextInfo { PluralRule = PluralRules.GetPluralRule(timeTextInfoData.PluralRule), Ptxt_week = timeTextInfoData.Ptxt_week, Ptxt_day = timeTextInfoData.Ptxt_day, Ptxt_hour = timeTextInfoData.Ptxt_hour, Ptxt_minute = timeTextInfoData.Ptxt_minute, Ptxt_second = timeTextInfoData.Ptxt_second, Ptxt_millisecond = timeTextInfoData.Ptxt_millisecond, Ptxt_w = timeTextInfoData.Ptxt_w, Ptxt_d = timeTextInfoData.Ptxt_d, Ptxt_h = timeTextInfoData.Ptxt_h, Ptxt_m = timeTextInfoData.Ptxt_m, Ptxt_s = timeTextInfoData.Ptxt_s, Ptxt_ms = timeTextInfoData.Ptxt_ms, Ptxt_lessThan = timeTextInfoData.Ptxt_lessThan }; } } internal struct TimeTextInfoData { public string PluralRule { get; set; } public string[] Ptxt_week { get; set; } public string[] Ptxt_day { get; set; } public string[] Ptxt_hour { get; set; } public string[] Ptxt_minute { get; set; } public string[] Ptxt_second { get; set; } public string[] Ptxt_millisecond { get; set; } public string[] Ptxt_w { get; set; } public string[] Ptxt_d { get; set; } public string[] Ptxt_h { get; set; } public string[] Ptxt_m { get; set; } public string[] Ptxt_s { get; set; } public string[] Ptxt_ms { get; set; } public string Ptxt_lessThan { get; set; } } [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 { [CompilerGenerated] private sealed class <AllFlags>d__3 : IEnumerable<TimeSpanFormatOptions>, IEnumerable, IEnumerator<TimeSpanFormatOptions>, IEnumerator, IDisposable { private int <>1__state; private TimeSpanFormatOptions <>2__current; private int <>l__initialThreadId; private TimeSpanFormatOptions timeSpanFormatOptions; public TimeSpanFormatOptions <>3__timeSpanFormatOptions; private uint <value>5__2; TimeSpanFormatOptions IEnumerator<TimeSpanFormatOptions>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AllFlags>d__3(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_004b; } <>1__state = -1; <value>5__2 = 1u; goto IL_0059; IL_004b: <value>5__2 <<= 1; goto IL_0059; IL_0059: if (<value>5__2 <= (uint)timeSpanFormatOptions) { if ((<value>5__2 & (uint)timeSpanFormatOptions) != 0) { <>2__current = (TimeSpanFormatOptions)<value>5__2; <>1__state = 1; return true; } goto IL_004b; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<TimeSpanFormatOptions> IEnumerable<TimeSpanFormatOptions>.GetEnumerator() { <AllFlags>d__3 <AllFlags>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <AllFlags>d__ = this; } else { <AllFlags>d__ = new <AllFlags>d__3(0); } <AllFlags>d__.timeSpanFormatOptions = <>3__timeSpanFormatOptions; return <AllFlags>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<TimeSpanFormatOptions>)this).GetEnumerator(); } } 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; } [IteratorStateMachine(typeof(<AllFlags>d__3))] public static IEnumerable<TimeSpanFormatOptions> AllFlags(this TimeSpanFormatOptions timeSpanFormatOptions) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AllFlags>d__3(-2) { <>3__timeSpanFormatOptions = timeSpanFormatOptions }; } 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) { return string.Join(" ", fromTime.ToTimeParts(options, timeTextInfo)); } internal static IList<string> ToTimeParts(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; } List<string> list = new List<string>(); 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, list.Count != 0, out var displayThisValue)) { continue; } PrepareOutput(num, timeSpanFormatOptions2 == _rangeMin, list.Count != 0, list, ref displayThisValue); if (displayThisValue) { string unitText = _timeTextInfo.GetUnitText(timeSpanFormatOptions2, num, _abbreviate); if (!string.IsNullOrEmpty(unitText)) { list.Add(unitText); } } } return list; } 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, List<string> result, ref bool displayThisValue) { if (isRangeMin && !hasTextStarted) { displayThisValue = true; if (_lessThan && value < 1) { string unitText = _timeTextInfo.GetUnitText(_rangeMin, 1, _abbreviate); result.Add(_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, string[] units) { int num = ((units.Length != 1) ? pluralRule.Invoke((decimal)value, units.Length) : 0); return string.Format(units[num], 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, }; } } }