using 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.0")]
[assembly: AssemblyInformationalVersion("3.6.0+daaa16ddd5375a12657c63bcb5c08e74eca10b61")]
[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,
};
}
}
}