Commit 77c9c2ec authored by shrabbit's avatar shrabbit
Browse files

优化完成,速度可压至<1ms。

parent b2ea701e
Loading
Loading
Loading
Loading
+100 −57
Original line number Diff line number Diff line
using System.Text;
using System;

namespace VideoSlice.Cli;

@@ -11,25 +11,37 @@ public static class SimpleTimeSpanExpress
    /// <returns>时间表达式</returns>
    public static string ToString(TimeSpan timeSpan)
    {
        var days = timeSpan.Days;
        var hours = timeSpan.Hours;
        var minutes = timeSpan.Minutes;
        var seconds = timeSpan.Seconds;
        var milliseconds = timeSpan.Milliseconds;
        var microseconds = timeSpan.Microseconds;

        var len =
            GetStringLengthFast(timeSpan.Days) + 1
            + GetStringLengthFast(timeSpan.Hours) + 1
            + GetStringLengthFast(timeSpan.Minutes) + 1
            + GetStringLengthFast(timeSpan.Seconds) + 1
            + GetStringLengthFast(timeSpan.Milliseconds) + 2
            + GetStringLengthFast(timeSpan.Microseconds) + 2
            + 4;
        
        var sb = new StringBuilder(len);

        Append(timeSpan.Days, "d", sb);
        Append(timeSpan.Hours, "h", sb);
        Append(timeSpan.Minutes, "m", sb);
        Append(timeSpan.Seconds, "s", sb);
        Append(timeSpan.Milliseconds, "ms", sb);
        Append(timeSpan.Microseconds, "us", sb);
        
        return sb.ToString();
            GetStringLengthFast(days) + 1
            + GetStringLengthFast(hours) + 1
            + GetStringLengthFast(minutes) + 1
            + GetStringLengthFast(seconds) + 1;

        if (milliseconds != 0)
            len += GetStringLengthFast(milliseconds) + 2;
        if (microseconds != 0)
            len += GetStringLengthFast(microseconds) + 2;

        return string.Create(len, timeSpan, static (span, ts) =>
        {
            var pos = span.Length;

            if (ts.Microseconds != 0)
                AppendFromEnd(span, ref pos, ts.Microseconds, "us");
            if (ts.Milliseconds != 0)
                AppendFromEnd(span, ref pos, ts.Milliseconds, "ms");
            AppendFromEnd(span, ref pos, ts.Seconds, "s");
            AppendFromEnd(span, ref pos, ts.Minutes, "m");
            AppendFromEnd(span, ref pos, ts.Hours, "h");
            AppendFromEnd(span, ref pos, ts.Days, "d");
        });
    }

    /// <summary>
@@ -39,57 +51,88 @@ public static class SimpleTimeSpanExpress
    /// <returns></returns>
    public static TimeSpan ToTimeSpan(string str)
    {
        var timespan = TimeSpan.Zero;

        timespan = timespan.Add(TimeSpan.FromDays(Parse(str, "d")));
        timespan = timespan.Add(TimeSpan.FromHours(Parse(str, "h")));
        timespan = timespan.Add(TimeSpan.FromMinutes(Parse(str, "m")));
        timespan = timespan.Add(TimeSpan.FromSeconds(Parse(str, "s")));
        timespan = timespan.Add(TimeSpan.FromMilliseconds(Parse(str, "ms")));
        timespan = timespan.Add(TimeSpan.FromMicroseconds(Parse(str, "us")));
        var days = 0;
        var hours = 0;
        var minutes = 0;
        var seconds = 0;
        var milliseconds = 0;
        var microseconds = 0;

        return timespan;
    }
        var i = 0;
        var len = str.Length;

    private static void Append(int value, string unit, StringBuilder sb)
        while (i < len)
        {
        sb.Append($"{value}{unit}");
    }

    public static int Parse(string s, string unit)
    {
        var sliced = s.Split(unit);
            if (str[i] == '-')
                throw new InvalidOperationException("值不能为负数。");

        var str = Near(sliced[0]);
            if (!char.IsAsciiDigit(str[i]))
                throw new InvalidOperationException($"'{str[i]}' 不是有效的字符。");

        if (int.TryParse(str, out var value))
            var value = 0L;
            var numberStart = i;
            do
            {
            return value < 0 ? throw new InvalidOperationException("值不能为负数。") : value;
        }
                value = value * 10 + (str[i] - '0');
                if (value > int.MaxValue)
                    throw new InvalidOperationException(
                        $"'{str.Substring(numberStart, i - numberStart + 1)}' 不是一个有效的32位整数。");
                i++;
            } while (i < len && char.IsAsciiDigit(str[i]));

        throw new InvalidOperationException($"'{sliced[0]}' 不是一个有效的32位整数。");
    }
            var unitStart = i;
            while (i < len && !char.IsAsciiDigit(str[i]) && str[i] != '-')
                i++;

    private static string Near(string s)
    {
        var arr = new char[s.Length];
        var count = 0;
            var unitLen = i - unitStart;

        for (var i = s.Length - 1; i >= 0; i--)
            switch (unitLen)
            {
            if (char.IsAsciiDigit(s[i]))
                case 1:
                    switch (str[unitStart])
                    {
                arr[i] = s[i];
                count++;
                        case 'd': days = (int)value; break;
                        case 'h': hours = (int)value; break;
                        case 'm': minutes = (int)value; break;
                        case 's': seconds = (int)value; break;
                        default:
                            throw new InvalidOperationException($"'{str[unitStart]}' 不是有效的单位。");
                    }
                    break;

                case 2:
                    if (str[unitStart] == 'm' && str[unitStart + 1] == 's')
                        milliseconds = (int)value;
                    else if (str[unitStart] == 'u' && str[unitStart + 1] == 's')
                        microseconds = (int)value;
                    else
                        throw new InvalidOperationException($"'{str.Substring(unitStart, 2)}' 不是有效的单位。");
                    break;

                default:
                    throw new InvalidOperationException($"'{str.Substring(unitStart, unitLen)}' 不是有效的单位。");
            }
        }

        if (count == 0)
            throw new InvalidOperationException("只包含非数字字符串。");
        return new TimeSpan(days, hours, minutes, seconds, milliseconds, microseconds);
    }

    private static void AppendFromEnd(Span<char> span, ref int pos, int value, string unit)
    {
        for (var j = unit.Length - 1; j >= 0; j--)
            span[--pos] = unit[j];

        var negative = value < 0;
        var v = negative ? -(long)value : value;

        do
        {
            span[--pos] = (char)('0' + v % 10);
            v /= 10;
        } while (v != 0);

        return new string(arr, arr.Length - count, count);
        if (negative)
            span[--pos] = '-';
    }

    private static int GetStringLengthFast(int value)