Decompiled source of SmartFormat Extensions Time v3.5.0

BepInEx/core/SmartFormat.Extensions.Time/netstandard2.1/SmartFormat.Extensions.Time.dll

Decompiled 4 months ago
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, 
			};
		}
	}
}