├── .github ├── FUNDING.yml ├── dependabot.yml ├── workflows │ └── build.yml ├── copilot-instructions.md └── instructions │ ├── testing.instructions.md │ └── general.instructions.md ├── .vscode ├── settings.json └── tasks.json ├── tests └── Exceptionless.DateTimeExtensions.Tests │ ├── Properties │ └── AssemblyInfo.cs │ ├── RandomHelper.cs │ ├── Exceptionless.DateTimeExtensions.Tests.csproj │ ├── FormatParsers │ ├── PartParsers │ │ ├── YearPartParserTests.cs │ │ ├── MonthPartParserTests.cs │ │ ├── NamedDayPartParserTests.cs │ │ ├── PartParserTestsBase.cs │ │ ├── MonthDayPartParserTests.cs │ │ ├── AmountTimeRelationPartParserTests.cs │ │ ├── MonthRelationPartParserTests.cs │ │ ├── ExplicitDatePartParserTests.cs │ │ ├── SingleTimeRelationPartParserTests.cs │ │ ├── WildcardPartParserTests.cs │ │ └── DateMathPartParserTests.cs │ ├── YearFormatParserTests.cs │ ├── NamedDayFormatParserTests.cs │ ├── MonthFormatParserTests.cs │ ├── MonthDayFormatParserTests.cs │ ├── FormatParserTestsBase.cs │ ├── RelationAmountTimeFormatParserTests.cs │ ├── MonthRelationFormatParserTests.cs │ ├── SingleTimeRelationFormatParserTests.cs │ ├── ExplicitDateFormatParserTests.cs │ └── TwoPartFormatParserTests.cs │ ├── DateTimeExtensionsTests.cs │ ├── TimeSpanExtensionTests.cs │ ├── TimeUnitTests.cs │ ├── BusinessDayTests.cs │ └── DateTimeRangeTests.cs ├── src └── Exceptionless.DateTimeExtensions │ ├── Exceptionless.DateTimeExtensions.csproj │ ├── FormatParsers │ └── FormatParsers │ │ ├── IFormatParser.cs │ │ ├── PriorityAttribute.cs │ │ ├── PartParsers │ │ ├── IPartParser.cs │ │ ├── YearPartParser.cs │ │ ├── WildcardPartParser.cs │ │ ├── MonthPartParser.cs │ │ ├── SingleTimeRelationPartParser.cs │ │ ├── MonthDayPartParser.cs │ │ ├── NamedDayPartParser.cs │ │ ├── DateMathPartParser.cs │ │ ├── ExplicitDatePartParser.cs │ │ ├── MonthRelationPartParser.cs │ │ └── AmountTimeRelationPartParser.cs │ │ ├── YearFormatParser.cs │ │ ├── SingleTimeRelationFormatParser.cs │ │ ├── MonthFormatParser.cs │ │ ├── MonthDayFormatParser.cs │ │ ├── NamedDayFormatParser.cs │ │ ├── ExplicitDateFormatParser.cs │ │ ├── Helper.cs │ │ ├── MonthRelationFormatParser.cs │ │ ├── RelationAmountTimeFormatParser.cs │ │ └── TwoPartFormatParser.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── TypeHelper.cs │ ├── BusinessDay.cs │ ├── TimeUnit.cs │ ├── DateTimeRange.cs │ ├── TimeSpanExtensions.cs │ ├── BusinessWeek.cs │ └── DateTimeExtensions.cs ├── Exceptionless.DateTimeExtensions.slnx ├── .gitattributes ├── .gitignore ├── .editorconfig ├── README.md └── LICENSE.txt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: exceptionless 2 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "millis", 4 | "timespan" 5 | ] 6 | } -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: nuget 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 -------------------------------------------------------------------------------- /tests/Exceptionless.DateTimeExtensions.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | [assembly: Xunit.CollectionBehavior(DisableTestParallelization = true, MaxParallelThreads = 1)] 2 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/Exceptionless.DateTimeExtensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/FormatParsers/FormatParsers/IFormatParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Exceptionless.DateTimeExtensions.FormatParsers; 4 | 5 | public interface IFormatParser 6 | { 7 | DateTimeRange Parse(string content, DateTimeOffset relativeBaseTime); 8 | } 9 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build: 6 | uses: FoundatioFx/Foundatio/.github/workflows/build-workflow.yml@main 7 | with: 8 | org: exceptionless 9 | secrets: 10 | NUGET_KEY: ${{ secrets.NUGET_KEY }} 11 | FEEDZ_KEY: ${{ secrets.FEEDZ_KEY }} 12 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/FormatParsers/FormatParsers/PriorityAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Exceptionless.DateTimeExtensions.FormatParsers; 4 | 5 | public class PriorityAttribute : Attribute 6 | { 7 | public PriorityAttribute(int priority) 8 | { 9 | Priority = priority; 10 | } 11 | 12 | public int Priority { get; private set; } 13 | } 14 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/FormatParsers/FormatParsers/PartParsers/IPartParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Exceptionless.DateTimeExtensions.FormatParsers.PartParsers; 5 | 6 | public interface IPartParser 7 | { 8 | Regex Regex { get; } 9 | DateTimeOffset? Parse(Match match, DateTimeOffset relativeBaseTime, bool isUpperLimit); 10 | } 11 | -------------------------------------------------------------------------------- /Exceptionless.DateTimeExtensions.slnx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("Exceptionless.DateTimeExtensions.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a9357232b9bcad78fd310297fdb41bf42816ee2ca9ccdace999889de2badb6f06df2de1d9f2c8cb17b21f5311f11d6bb328d55e0dd9fe8adc5e2dc4610028c1bdacb3355d2e239b81d0bb0ac83e615fc641f8a3ec49e4fad8e305994953d448ef7b38e8c256601e54af19c035b562e3e5e5461c2a93b8dd11936e451b05034a2")] 4 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/FormatParsers/FormatParsers/PartParsers/YearPartParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Exceptionless.DateTimeExtensions.FormatParsers.PartParsers; 5 | 6 | [Priority(70)] 7 | public class YearPartParser : IPartParser 8 | { 9 | private static readonly Regex _parser = new(@"\G(?\d{4})", RegexOptions.Compiled); 10 | public Regex Regex => _parser; 11 | 12 | public DateTimeOffset? Parse(Match match, DateTimeOffset relativeBaseTime, bool isUpperLimit) 13 | { 14 | int year = Int32.Parse(match.Groups["year"].Value); 15 | return isUpperLimit ? relativeBaseTime.ChangeYear(year).EndOfYear() : relativeBaseTime.ChangeYear(year).StartOfYear(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/FormatParsers/FormatParsers/PartParsers/WildcardPartParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Exceptionless.DateTimeExtensions.FormatParsers.PartParsers; 5 | 6 | [Priority(1)] 7 | public class WildcardPartParser : IPartParser 8 | { 9 | private static readonly Regex _wildcardRegex = new(@"\G\s*\*(?=\s|\]|\}|$)", RegexOptions.Compiled | RegexOptions.IgnoreCase); 10 | 11 | public Regex Regex => _wildcardRegex; 12 | 13 | public DateTimeOffset? Parse(Match match, DateTimeOffset relativeBaseTime, bool isUpperLimit) 14 | { 15 | if (!match.Success) 16 | return null; 17 | 18 | return isUpperLimit ? DateTimeOffset.MaxValue : DateTimeOffset.MinValue; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/Exceptionless.DateTimeExtensions.Tests/RandomHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Exceptionless.DateTimeExtensions.Tests; 4 | 5 | public static class RandomHelper 6 | { 7 | static readonly Random _rnd = new(); 8 | 9 | public static DateTime GetRandomDate(DateTime from, DateTime to) 10 | { 11 | var range = to - from; 12 | 13 | var randTimeSpan = new TimeSpan((long)(_rnd.NextDouble() * range.Ticks)); 14 | 15 | return from + randTimeSpan; 16 | } 17 | 18 | public static DateTimeOffset GetRandomDate(DateTimeOffset from, DateTimeOffset to) 19 | { 20 | var range = to - from; 21 | 22 | var randTimeSpan = new TimeSpan((long)(_rnd.NextDouble() * range.Ticks)); 23 | 24 | return from + randTimeSpan; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/FormatParsers/FormatParsers/YearFormatParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Exceptionless.DateTimeExtensions.FormatParsers; 5 | 6 | [Priority(80)] 7 | public class YearFormatParser : IFormatParser 8 | { 9 | private static readonly Regex _parser = new(@"^\s*(?\d{4})\s*$", RegexOptions.Compiled); 10 | 11 | public DateTimeRange Parse(string content, DateTimeOffset relativeBaseTime) 12 | { 13 | var m = _parser.Match(content); 14 | if (!m.Success) 15 | return null; 16 | 17 | int year = Int32.Parse(m.Groups["year"].Value); 18 | return new DateTimeRange(relativeBaseTime.ChangeYear(year).StartOfYear(), relativeBaseTime.ChangeYear(year).EndOfYear()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Exceptionless.DateTimeExtensions/FormatParsers/FormatParsers/SingleTimeRelationFormatParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace Exceptionless.DateTimeExtensions.FormatParsers; 5 | 6 | [Priority(70)] 7 | public class SingleTimeRelationFormatParser : RelationAmountTimeFormatParser 8 | { 9 | private static readonly Regex _parser = new(String.Format(@"^\s*(?{0})\s+(?