< Summary - Code Coverage

Information
Class: Plainquire.Filter.Abstractions.DateTimeRangeExtensions
Assembly: Plainquire.Filter.Abstractions
File(s): /home/runner/work/plainquire/plainquire/Plainquire.Filter/Plainquire.Filter.Abstractions/Extensions/DateTimeRangeExtensions.cs
Tag: 64_13932151703
Line coverage
92%
Covered lines: 74
Uncovered lines: 6
Coverable lines: 80
Total lines: 138
Line coverage: 92.5%
Branch coverage
82%
Covered branches: 43
Total branches: 52
Branch coverage: 82.6%
Method coverage
100%
Covered methods: 6
Total methods: 6
Method coverage: 100%

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
CreateDateTimeRange(...)81.25%161692.3%
TryConvertDateTimeRangeFormattedString(...)100%66100%
TryConvertIso8601FormattedString(...)83.33%66100%
TryConvertUnknownFormattedString(...)70%101078.57%
ParseDateTimePart(...)100%22100%
ParseOffset(...)83.33%121287.5%

File(s)

/home/runner/work/plainquire/plainquire/Plainquire.Filter/Plainquire.Filter.Abstractions/Extensions/DateTimeRangeExtensions.cs

#LineLine coverage
 1using System;
 2using System.Globalization;
 3using System.Text.RegularExpressions;
 4
 5namespace Plainquire.Filter.Abstractions;
 6
 7/// <summary>
 8/// Extension methods for <see cref="DateTime"/>.
 9/// </summary>
 10public static class DateTimeRangeExtensions
 11{
 12    /// <summary>
 13    /// Creates a new <see cref="Range{TType}"/> using given values. Values not given are expanded to start and end of i
 14    /// </summary>
 15    private static Range<DateTimeOffset> CreateDateTimeRange(int? year = null, int? month = null, int? day = null, int? 
 16    {
 764317        var start = new DateTimeOffset(
 764318            year ?? DateTimeOffset.MinValue.Year,
 764319            month ?? 1,
 764320            day ?? 1,
 764321            hour ?? 0,
 764322            minute ?? 0,
 764323            second ?? 0,
 764324            millisecond ?? 0,
 764325            offset);
 26
 757127        var end = start;
 757128        if (year == null)
 029            end = DateTimeOffset.MaxValue;
 757130        else if (month == null)
 40831            end = end.AddYears(1);
 716332        else if (day == null)
 36033            end = end.AddMonths(1);
 680334        else if (hour == null)
 322835            end = end.AddDays(1);
 357536        else if (minute == null)
 21637            end = end.AddHours(1);
 335938        else if (second == null)
 36039            end = end.AddMinutes(1);
 299940        else if (millisecond == null)
 299941            end = end.AddSeconds(1);
 42        else
 043            end = end.AddMilliseconds(millisecond.Value);
 44
 757145        return new Range<DateTimeOffset>(start, end);
 46    }
 47
 48    internal static bool TryConvertDateTimeRangeFormattedString(string value, IFormatProvider? cultureInfo, out Range<Da
 49    {
 717950        dateTimeRange = new Range<DateTimeOffset>(DateTimeOffset.MinValue, DateTimeOffset.MinValue);
 51
 717952        var startAndEnd = Regex.Match(value, "^(?<start>.+?)_(?<end>.+)$", RegexOptions.None, RegexDefaults.Timeout);
 717953        if (!startAndEnd.Success)
 541554            return false;
 55
 176456        var startParsed = TryConvertIso8601FormattedString(startAndEnd.Groups["start"].Value, cultureInfo, out var start
 176457        var endParsed = TryConvertIso8601FormattedString(startAndEnd.Groups["end"].Value, cultureInfo, out var end);
 176458        if (!startParsed || !endParsed)
 18059            return false;
 60
 158461        dateTimeRange = new Range<DateTimeOffset>(start.Start, end.End);
 158462        return true;
 63    }
 64
 65    internal static bool TryConvertIso8601FormattedString(string value, IFormatProvider? cultureInfo, out Range<DateTime
 66    {
 912367        dateTimeRange = new Range<DateTimeOffset>(DateTimeOffset.MinValue, DateTimeOffset.MinValue);
 68
 69        const string offsetPattern = @"^(?<datetime>.+?)(?<offset>Z|[\+\-]\d{1,2}:\d{1,2})?$";
 70        const string dateTimePattern = @"^(?<year>\d\d\d\d)(\D(?<month>\d\d))?(\D(?<day>\d\d))?(\D(?<hour>\d\d))?(\D(?<m
 71
 912372        var dateTimeAndOffset = Regex.Match(value, offsetPattern, RegexOptions.None, RegexDefaults.Timeout);
 912373        if (!dateTimeAndOffset.Success)
 32474            return false;
 75
 879976        var dateTime = dateTimeAndOffset.Groups["datetime"].Value;
 879977        var offset = dateTimeAndOffset.Groups["offset"].Value;
 78
 879979        var dateAndTime = Regex.Match(dateTime, dateTimePattern, RegexOptions.ExplicitCapture, RegexDefaults.Timeout);
 879980        if (!dateAndTime.Success)
 115681            return false;
 82
 83        try
 84        {
 764385            var year = ParseDateTimePart(dateAndTime, "year", cultureInfo) ?? throw new InvalidOperationException($"Year
 764386            var month = ParseDateTimePart(dateAndTime, "month", cultureInfo);
 764387            var day = ParseDateTimePart(dateAndTime, "day", cultureInfo);
 764388            var hour = ParseDateTimePart(dateAndTime, "hour", cultureInfo);
 764389            var minute = ParseDateTimePart(dateAndTime, "minute", cultureInfo);
 764390            var second = ParseDateTimePart(dateAndTime, "second", cultureInfo);
 764391            var offsetTimeSpan = ParseOffset(offset);
 764392            dateTimeRange = CreateDateTimeRange(year, month, day, hour, minute, second, null, offsetTimeSpan);
 757193            return true;
 94        }
 14495        catch (ArgumentException) { }
 96
 7297        return false;
 757198    }
 99
 100    internal static bool TryConvertUnknownFormattedString(string value, CultureInfo? cultureInfo, out Range<DateTimeOffs
 101    {
 1084102        var result = DateTimeOffset.TryParse(value, cultureInfo, DateTimeStyles.AssumeUniversal, out var startDate);
 103
 104        DateTimeOffset endDate;
 1084105        if (startDate.Second != 0)
 0106            endDate = startDate.AddSeconds(1);
 1084107        else if (startDate.Minute != 0)
 0108            endDate = startDate.AddMinutes(1);
 1084109        else if (startDate.Hour != 0)
 0110            endDate = startDate.AddHours(1);
 1084111        else if (startDate.Day != 1)
 72112            endDate = startDate.AddDays(1);
 1012113        else if (startDate.Month != 1)
 72114            endDate = startDate.AddMonths(1);
 115        else
 940116            endDate = startDate.AddYears(1);
 117
 1084118        dateTimeRange = new Range<DateTimeOffset>(startDate, endDate);
 1084119        return result;
 120    }
 121
 122    private static int? ParseDateTimePart(Match lMatch, string name, IFormatProvider? cultureInfo)
 45858123        => int.TryParse(lMatch.Groups[name].Value, NumberStyles.Any, cultureInfo, out var intValue) ? intValue : null;
 124
 125    private static TimeSpan ParseOffset(string offset)
 126    {
 7643127        if (string.IsNullOrEmpty(offset) || offset.EqualsOrdinal("Z"))
 5099128            return TimeSpan.Zero;
 129
 2544130        var offsetHasSign = offset[0] == '+' || offset[0] == '-';
 2544131        var absoluteOffset = offsetHasSign ? offset[1..] : offset;
 2544132        if (!TimeSpan.TryParse(absoluteOffset, out var timeSpan))
 0133            return TimeSpan.Zero;
 134
 2544135        var signMultiplier = offset[0] == '+' ? 1 : -1;
 2544136        return timeSpan * signMultiplier;
 137    }
 138}