### Install CodoMetis.ValueRanges Package Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Use the dotnet CLI to add the CodoMetis.ValueRanges package to your project. Requires .NET 10 or later. ```sh dotnet add package CodoMetis.ValueRanges ``` -------------------------------- ### Add EF Core PostgreSQL Package Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Install the companion package to enable ValueRanges integration with PostgreSQL via EF Core. This package maps range types to PostgreSQL range columns. ```bash dotnet add package CodoMetis.ValueRanges.EFCore.PostgreSQL ``` -------------------------------- ### Create Unbounded Start Date Ranges Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Shows how to create date ranges unbounded on the left. The end boundary is exclusive by default, but can be made inclusive. ```csharp // Unbounded on the left — end exclusive by default DateRange upToToday = DateRange.CreateUnboundedStart(DateOnly.FromDateTime(DateTime.Today)); // (-∞, today) // Inclusive variant: DateRange throughToday = DateRange.CreateUnboundedStart(DateOnly.FromDateTime(DateTime.Today), endInclusive: true); ``` -------------------------------- ### Create Unbounded End Int32 Range Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Illustrates creating an integer range that is unbounded on the right. The start boundary is inclusive by default. ```csharp // Unbounded on the right — start inclusive by default Int32Range fromFive = Int32Range.CreateUnboundedEnd(5); // [5, +∞) ``` -------------------------------- ### Querying Multirange Contains and Union Operators Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Shows examples of checking if a multirange contains a value and performing union operations using multirange operators. ```csharp // b."BlockedDays" @> @day, multirange + - * operators, complement, ... bookings.Where(b => b.BlockedDays.Contains(day)); bookings.Select(b => b.BlockedDays | b.Period); ``` -------------------------------- ### Creating Finite Date Ranges Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Illustrates creating a finite DateRange using factory methods, which translates to guarded range constructor calls in SQL. ```csharp // CASE WHEN b."From" <= b."To" THEN daterange(b."From", b."To", '[]') ELSE 'empty' END bookings.Where(b => DateRange.CreateFinite(b.From, b.To).Contains(day)); ``` -------------------------------- ### Create Finite Int32 Ranges Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates creating closed and half-open finite integer ranges. The `CreateFinite` method returns an empty range for degenerate or inverted intervals. ```csharp // Bounded on both sides Int32Range closed = Int32Range.CreateFinite(1, 10); // [1, 10] Int32Range half = Int32Range.CreateFinite(1, 10, endInclusive: false); // [1, 10) ``` -------------------------------- ### Create Infinite and Empty Int32 Ranges Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates creating a range that is unbounded on both ends and an explicitly empty range. ```csharp // Unbounded on both ends Int32Range everything = Int32Range.Infinite; // (-∞, +∞) // Explicitly empty Int32Range empty = Int32Range.Empty; ``` -------------------------------- ### RangeSet Construction and Normalization Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Shows how to construct a RangeSet and how it automatically normalizes overlapping and adjacent ranges. ```csharp using IntSet = RangeSet; // Construction normalizes: [1, 5] and [6, 10] are adjacent for int and merge. var set = IntSet.From([ Int32Range.CreateFinite(6, 10), Int32Range.CreateFinite(1, 5), Int32Range.CreateFinite(20, 30) ]); // { [1, 10], [20, 30] } ``` -------------------------------- ### Formatting Basic Int32 Ranges Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates the default string representation for various Int32Range types, including finite, unbounded, and empty ranges. ```csharp Int32Range.CreateFinite(1, 10).ToString() // "[1,10]" Int32Range.CreateFinite(1, 10, endInclusive: false) .ToString() // "[1,10)" Int32Range.CreateUnboundedStart(5).ToString() // "(,5]" Int32Range.CreateUnboundedEnd(5).ToString() // "[5,)" Int32Range.Infinite.ToString() // "(,)" Int32Range.Empty.ToString() // "empty" ``` -------------------------------- ### Int32Range PostgreSQL &< / &> Equivalents Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Implements PostgreSQL's &< (does not extend to the right of) and &> (does not extend to the left of) range comparison logic. ```csharp // Does not extend to the right of other (&<) Int32Range.CreateFinite(1, 5).DoesNotExtendRightOf(Int32Range.CreateFinite(1, 10)); // true // Does not extend to the left of other (&>) Int32Range.CreateFinite(3, 10).DoesNotExtendLeftOf(Int32Range.CreateFinite(1, 10)); // true ``` -------------------------------- ### RangeSet Set Operations (Union, Intersect, Except) Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates various set operations on a RangeSet, including union, intersection, and difference, using both methods and operator aliases. ```csharp // Set operations — single-range and bulk variants, with operator aliases (|, &, -) set.Union(Int32Range.CreateFinite(11, 19)); // { [1, 30] } — bridges the gap set | Int32Range.CreateFinite(11, 19); // { [1, 30] } set.Intersect(Int32Range.CreateFinite(5, 25)); // { [5, 10], [20, 25] } set & Int32Range.CreateFinite(5, 25); // { [5, 10], [20, 25] } set.Except(Int32Range.CreateFinite(4, 6)); // { [1, 3], [7, 10], [20, 30] } set - Int32Range.CreateFinite(4, 6); // { [1, 3], [7, 10], [20, 30] } ``` -------------------------------- ### Formatting DateRange with Custom Format Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates how to format a DateRange with a custom format string to control the display of date components. ```csharp ((IFormattable)DateRange.CreateFinite(new DateOnly(2025, 1, 1), new DateOnly(2025, 3, 31))) .ToString("MMM d yyyy", CultureInfo.InvariantCulture) // "[Jan 1 2025,Mar 31 2025]" ``` -------------------------------- ### Range Except Operation Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates the Except operation on a single range, showing how it can split a range into two. ```csharp var range = Int32Range.CreateFinite(1, 10); var remove = Int32Range.CreateFinite(4, 6); // [4, 6] is interior to [1, 10] — the result is split in two var result = range.Except(remove); // result[0] = [1, 4) // result[1] = (6, 10] ``` -------------------------------- ### Querying with Range Union (Multirange) Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates performing a union of two ranges, which results in a multirange. This operation translates to the PostgreSQL '+' operator for multiranges. ```csharp // datemultirange(b."Period") + datemultirange(@other) (union -> multirange) bookings.Select(b => b.Period.Union(other)); ``` -------------------------------- ### Pattern Matching on Int32Range Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates exhaustive pattern matching on nested sealed records for Int32Range. The private constructor ensures completeness of the switch statement. ```csharp string Describe(Int32Range range) => range switch { Int32Range.EmptyRange => "empty", Int32Range.Finite f => $"[{f.Start}, {f.End}]", Int32Range.UnboundedStart s => $"(-∞, {s.End}]", Int32Range.UnboundedEnd e => $"[{e.Start}, +∞)", Int32Range.Infinity => "(-∞, +∞)", }; ``` -------------------------------- ### Formatting RangeSet Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Shows the string representation for a RangeSet, formatted as a PostgreSQL multirange literal. ```csharp IntSet.From([Int32Range.CreateFinite(1, 5), Int32Range.CreateFinite(7, 10)]) .ToString() // "{[1,5],[7,10]}" IntSet.Empty.ToString() // "{}" IntSet.Infinite.ToString() // "{(,)}" ``` -------------------------------- ### Formatting DateTimeOffsetRange Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Illustrates the string representation for a DateTimeOffsetRange, including timezone information. ```csharp DateTimeOffsetRange.CreateFinite( new DateTimeOffset(2024, 6, 1, 0, 0, 0, TimeSpan.FromHours(1)), new DateTimeOffset(2024, 7, 1, 0, 0, 0, TimeSpan.FromHours(1))).ToString() // "[2024-06-01T00:00:00.0000000+01:00,2024-07-01T00:00:00.0000000+01:00)" ``` -------------------------------- ### Formatting DateRange Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Shows the string representation for a DateRange, using the standard PostgreSQL range literal format. ```csharp DateRange.CreateFinite(new DateOnly(2025, 1, 1), new DateOnly(2025, 3, 31)).ToString() // "[2025-01-01,2025-03-31]" ``` -------------------------------- ### Querying with Range Intersection Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Illustrates how to find the intersection of two ranges using the LINQ Intersect method, translating to the PostgreSQL '*' operator. ```csharp // b."Period" * @other (intersection) bookings.Select(b => b.Period.Intersect(other)); ``` -------------------------------- ### RangeSet Structural Equality Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Illustrates that two RangeSets are considered equal if they normalize to the same structure, regardless of the initial input. ```csharp var a = IntSet.From([Int32Range.CreateFinite(1, 10)]); var b = IntSet.From([Int32Range.CreateFinite(1, 5), Int32Range.CreateFinite(6, 10)]); a.Equals(b); // true — both normalize to { [1, 10] } ``` -------------------------------- ### RangeSet Complement Operation Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Shows how to compute the complement of a RangeSet, representing all values not covered by the set. ```csharp // Complement — every value not covered by the set set.Complement(); // { (-∞, 0], [11, 19], [31, +∞) } ``` -------------------------------- ### Configure EF Core to Use Value Ranges Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Enable ValueRanges support in your DbContext options with a single line of code. No manual configuration of value converters, comparers, or column types is needed. ```csharp options.UseNpgsql(connectionString, npgsql => npgsql.UseValueRanges()); ``` -------------------------------- ### Update State-Check Methods to Use Parentheses Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md In v3.0.0, state-check methods like IsEmpty, IsFinite, etc., are extension methods and require parentheses. This change improves EF Core compatibility for LINQ translation. ```csharp // v2.x if (range.IsEmpty) { … } // v3.0.0 if (range.IsEmpty()) { … } ``` -------------------------------- ### Previous ToString() Format (v1.x) Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md In v1.x, ToString() returned the C# record representation. This format is no longer used in v2.0.0 and later. ```csharp // Finite { Start = 1, End = 10, StartInclusive = True, EndInclusive = True } ``` -------------------------------- ### RangeSet Query Operations Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Illustrates common query operations on a RangeSet, such as Contains and Overlaps. ```csharp // Query operations set.Contains(7); // true set.Contains(Int32Range.CreateFinite(2, 8)); // true — within a single element set.Overlaps(Int32Range.CreateFinite(15, 25)); // true ``` -------------------------------- ### Current ToString() Format (v2.0.0+) Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md From v2.0.0, ToString() returns the PostgreSQL range literal format, which is more compact and standard. ```csharp // [1,10] ``` -------------------------------- ### Serialize and Deserialize Range Objects to JSON Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Ranges serialize as JSON strings in PostgreSQL literal format. Use the registered converters to serialize range objects to JSON strings and deserialize them back. Null JSON tokens are rejected; use the literal "empty" for empty ranges. ```csharp var range = Int32Range.CreateFinite(1, 10); string json = JsonSerializer.Serialize(range, options); // "[1,10]" var back = JsonSerializer.Deserialize(json, options); // back == Int32Range.CreateFinite(1, 10) ``` ```csharp // Multirange var set = RangeSet.From([ Int32Range.CreateFinite(1, 5), Int32Range.CreateFinite(7, 10) ]); string setJson = JsonSerializer.Serialize(set, options); // "{[1,5],[7,10]}" ``` ```csharp // Works with all six range types and their multirange counterparts var dates = JsonSerializer.Serialize( DateRange.CreateFinite(new DateOnly(2025, 1, 1), new DateOnly(2025, 12, 31)), options); // "[2025-01-01,2025-12-31]" ``` -------------------------------- ### Querying with Range Overlaps Operator Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Shows how to query for overlapping ranges using the LINQ Overlaps method, which translates to the PostgreSQL '&&' operator. ```csharp // b."Period" && b."Blocked", b."Period" << @other, b."Period" -|- @other, ... bookings.Where(b => b.Period.Overlaps(other)); ``` -------------------------------- ### Register Range Converters for System.Text.Json Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Register the provided System.Text.Json converters to enable serialization and deserialization of range types. Use AddRangeConverters() for all types or RangeJsonConverterFactory for automatic registration. ```csharp using CodoMetis.ValueRanges.Serialization; var options = new JsonSerializerOptions().AddRangeConverters(); ``` ```csharp var options = new JsonSerializerOptions { Converters = { new RangeJsonConverterFactory() } }; ``` ```csharp builder.Services.ConfigureHttpJsonOptions(o => o.SerializerOptions.AddRangeConverters()); ``` -------------------------------- ### Int32Range Union with Disjoint Ranges Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Computes the union of two disjoint Int32Range instances. The result is a RangeSet containing both ranges. ```csharp var a = Int32Range.CreateFinite(1, 5); var c = Int32Range.CreateFinite(7, 10); var ac = a.Union(c); // { [1, 5], [7, 10] } — disjoint, two elements ac.Count; // 2 ac[1]; // [7, 10] ``` -------------------------------- ### Parse PostgreSQL Range Literals Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Use the static Parse and TryParse methods to convert PostgreSQL range literals into range objects. Discrete types canonicalize on parse, e.g., '[1,10)' parses to '[1,9]'. ```csharp var r1 = Int32Range.Parse("[1,10]", null); // Finite [1, 10] var r2 = Int32Range.Parse("(,5]", null); // UnboundedStart (−∞, 5] var r3 = Int32Range.Parse("[3,)", null); // UnboundedEnd [3, +∞) var r4 = Int32Range.Parse("(,)", null); // Infinity (−∞, +∞) var r5 = Int32Range.Parse("empty", null); // Empty if (Int32Range.TryParse(userInput, null, out var range)) Console.WriteLine(range); ``` ```csharp Int32Range.Parse("[1,10)", null).ToString() // "[1,9]" ``` -------------------------------- ### DateRange Containment Checks Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Illustrates point and range containment using the Contains method on DateRange. The IsContainedBy method provides a symmetric alias. ```csharp var sprint = DateRange.CreateFinite(new DateOnly(2025, 1, 6), new DateOnly(2025, 1, 17)); sprint.Contains(new DateOnly(2025, 1, 10)); // true — point containment sprint.Contains(new DateOnly(2025, 1, 20)); // false var inner = DateRange.CreateFinite(new DateOnly(2025, 1, 8), new DateOnly(2025, 1, 14)); sprint.Contains(inner); // true — range containment inner.IsContainedBy(sprint); // true — symmetric alias ``` -------------------------------- ### Int32Range Directional Comparison Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Compares the relative positions of two Int32Range instances using strictly left of and strictly right of checks. ```csharp Int32Range.CreateFinite(1, 3).IsStrictlyLeftOf(Int32Range.CreateFinite(5, 9)); // true Int32Range.CreateFinite(1, 5).IsStrictlyLeftOf(Int32Range.CreateFinite(5, 9)); // false — they share 5 Int32Range.CreateFinite(7, 9).IsStrictlyRightOf(Int32Range.CreateFinite(1, 5)); // true ``` -------------------------------- ### Int32Range Union with Overlap/Adjacency Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Computes the union of two Int32Range instances. If they overlap or are adjacent, the result is a single merged range. ```csharp var a = Int32Range.CreateFinite(1, 5); var b = Int32Range.CreateFinite(5, 10); var ab = a.Union(b); // { [1, 10] } — overlapping, one element ab.Count; // 1 ``` -------------------------------- ### Parse PostgreSQL Multirange Literals Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md The RangeSet type parses multirange literals, allowing for the creation and access of multiple ranges within a single set. ```csharp var set = RangeSet.Parse("{[1,5],[7,10]}", null); set.Count; // 2 set[0]; // [1, 5] set[1]; // [7, 10] ``` -------------------------------- ### Querying with Range Contains Operator Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Demonstrates how to use the LINQ Contains method on a DateRange, which translates to the PostgreSQL '@>' operator for checking if a range contains a specific value. ```csharp var day = new DateOnly(2024, 6, 15); // b."Period" @> @day bookings.Where(b => b.Period.Contains(day)); ``` -------------------------------- ### DecimalRange Adjacency Check (Continuous) Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Checks if two continuous DecimalRange instances are adjacent, considering inclusiveness of bounds. ```csharp // Continuous: touching bounds with complementary inclusiveness var x = DecimalRange.CreateFinite(1m, 5m, endInclusive: true); // [1, 5] var y = DecimalRange.CreateFinite(5m, 10m, startInclusive: false); // (5, 10) x.IsAdjacentTo(y); // true — one side claims 5, the other does not ``` -------------------------------- ### Int32Range Intersection Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Calculates the intersection of two Int32Range instances. Returns Empty if there is no overlap. ```csharp var a = Int32Range.CreateFinite(1, 10); var b = Int32Range.CreateFinite(5, 15); Int32Range intersection = a.Intersect(b); // [5, 10] a.Intersect(Int32Range.CreateFinite(11, 20)); // Empty — no overlap ``` -------------------------------- ### Int32Range Adjacency Check (Discrete) Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Determines if two discrete Int32Range instances are adjacent, meaning they are contiguous with no gap or overlap. ```csharp // Discrete: consecutive integer values are adjacent var a = Int32Range.CreateFinite(1, 5); var b = Int32Range.CreateFinite(6, 10); a.IsAdjacentTo(b); // true — NextValueAfter(5) == 6 ``` -------------------------------- ### Int32Range Overlap Check Source: https://github.com/caffeinatedcoder/codometis.valueranges/blob/main/README.md Checks if two Int32Range instances overlap. Overlap includes sharing a boundary point. ```csharp var a = Int32Range.CreateFinite(1, 5); var b = Int32Range.CreateFinite(5, 10); var c = Int32Range.CreateFinite(6, 10); a.Overlaps(b); // true — they share the point 5 a.Overlaps(c); // false ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.