1"use strict";(globalThis.webpackChunkvali_tempo_docs=globalThis.webpackChunkvali_tempo_docs||[]).push([[462],{9031(e,n,a){a.r(n),a.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>s,metadata:()=>r,toc:()=>c});const r=JSON.parse('{"id":"vali-range/overview","title":"Vali-Range Overview","description":"Vali-Range provides date range operations for .NET \u2014 check overlaps, containment, duration, and iterate over date ranges with precision.","source":"@site/docs/vali-range/overview.md","sourceDirName":"vali-range","slug":"/vali-range/overview","permalink":"/docs/vali-range/overview","draft":false,"unlisted":false,"editUrl":"https://github.com/UBF21/Vali-Tempo/tree/main/docs/vali-range/overview.md","tags":[],"version":"current","frontMatter":{"id":"overview","title":"Vali-Range Overview","sidebar_label":"Overview","description":"Vali-Range provides date range operations for .NET \u2014 check overlaps, containment, duration, and iterate over date ranges with precision.","keywords":["Vali-Range","date range",".NET","NuGet","overlap","C#","date interval"]},"sidebar":"docsSidebar","previous":{"title":"Changelog","permalink":"/docs/vali-time/changelog"},"next":{"title":"Examples","permalink":"/docs/vali-range/examples"}}');var t=a(4848),i=a(8453);const s={id:"overview",title:"Vali-Range Overview",sidebar_label:"Overview",description:"Vali-Range provides date range operations for .NET \u2014 check overlaps, containment, duration, and iterate over date ranges with precision.",keywords:["Vali-Range","date range",".NET","NuGet","overlap","C#","date interval"]},l="Vali-Range",d={},c=[{value:"Installation",id:"installation",level:2},{value:"Registration",id:"registration",level:2},{value:"DateRange Struct",id:"daterange-struct",level:2},{value:"IValiRange API",id:"ivalirange-api",level:2},{value:"Create",id:"create",level:3},{value:"LastUnits",id:"lastunits",level:3},{value:"NextUnits",id:"nextunits",level:3},{value:"ThisMonth / ThisWeek / ThisQuarter / ThisYear",id:"thismonth--thisweek--thisquarter--thisyear",level:3},{value:"Contains",id:"contains",level:3},{value:"Overlaps",id:"overlaps",level:3},{value:"IsContainedBy",id:"iscontainedby",level:3},{value:"Intersection",id:"intersection",level:3},{value:"Union",id:"union",level:3},{value:"Expand",id:"expand",level:3},{value:"Shrink",id:"shrink",level:3},{value:"Shift",id:"shift",level:3},{value:"IsAdjacent",id:"isadjacent",level:3},{value:"Merge",id:"merge",level:3},{value:"Gaps",id:"gaps",level:3},{value:"EachDay / EachWeek / EachMonth",id:"eachday--eachweek--eachmonth",level:3},{value:"EachWorkday",id:"eachworkday",level:3},{value:"SplitByDay / SplitByWeek / SplitByMonth / SplitByQuarter",id:"splitbyday--splitbyweek--splitbymonth--splitbyquarter",level:3},{value:"Complete Example",id:"complete-example",level:2}];function o(e){const n={blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"vali-range",children:"Vali-Range"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"IValiRange"})," provides a comprehensive set of date range operations built on the ",(0,t.jsx)(n.code,{children:"DateRange"})," struct. It supports creation, querying, set operations (union, intersection), enumeration, splitting, and calendar-aware workday iteration."]}),"\n",(0,t.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"dotnet add package Vali-Range\n"})}),"\n",(0,t.jsx)(n.h2,{id:"registration",children:"Registration"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"builder.Services.AddValiRange();\n// or via the meta-package:\nbuilder.Services.AddValiTempo();\n"})}),"\n",(0,t.jsx)(n.h2,{id:"daterange-struct",children:"DateRange Struct"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"DateRange"})," is a value type representing a closed date interval ",(0,t.jsx)(n.code,{children:"[Start, End]"}),"."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"var range = new DateRange(new DateTime(2025, 1, 1), new DateTime(2025, 3, 31));\nConsole.WriteLine(range.Start); // 2025-01-01\nConsole.WriteLine(range.End); // 2025-03-31\nConsole.WriteLine(range.Duration); // TimeSpan of 90 days\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Properties:"})}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Property"}),(0,t.jsx)(n.th,{children:"Type"}),(0,t.jsx)(n.th,{children:"Description"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"Start"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"DateTime"})}),(0,t.jsx)(n.td,{children:"Inclusive start date"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"End"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"DateTime"})}),(0,t.jsx)(n.td,{children:"Inclusive end date"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"Duration"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"TimeSpan"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"End - Start"})})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"TotalDays"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"int"})}),(0,t.jsx)(n.td,{children:"Number of calendar days"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"IsEmpty"})}),(0,t.jsx)(n.td,{children:(0,t.jsx)(n.code,{children:"bool"})}),(0,t.jsx)(n.td,{children:"True when Start == End or range is invali
1d"})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"ivalirange-api",children:"IValiRange API"}),"\n",(0,t.jsx)(n.h3,{id:"create",children:"Create"}),"\n",(0,t.jsxs)(n.p,{children:["Create a ",(0,t.jsx)(n.code,{children:"DateRange"})," from start and end dates:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange r = range.Create(new DateTime(2025, 1, 1), new DateTime(2025, 12, 31));\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange Create(DateTime start, DateTime end)"})]}),"\n",(0,t.jsx)(n.h3,{id:"lastunits",children:"LastUnits"}),"\n",(0,t.jsx)(n.p,{children:"Create a range covering the last N units before a reference date:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange last30Days = range.LastUnits(30, TimeUnit.Days);\nDateRange last3Months = range.LastUnits(3, TimeUnit.Months, referenceDate: DateTime.Today);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange LastUnits(int count, TimeUnit unit, DateTime? referenceDate = null)"})]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," ",(0,t.jsx)(n.code,{children:"amount"})," must be greater than 0. Passing 0 or a negative value throws ",(0,t.jsx)(n.code,{children:"ArgumentException"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"nextunits",children:"NextUnits"}),"\n",(0,t.jsx)(n.p,{children:"Create a range covering the next N units after a reference date:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange next7Days = range.NextUnits(7, TimeUnit.Days);\nDateRange nextQuarter = range.NextUnits(1, TimeUnit.Months, count: 3);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange NextUnits(int count, TimeUnit unit, DateTime? referenceDate = null)"})]}),"\n",(0,t.jsxs)(n.blockquote,{children:["\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note:"})," ",(0,t.jsx)(n.code,{children:"amount"})," must be greater than 0. Passing 0 or a negative value throws ",(0,t.jsx)(n.code,{children:"ArgumentException"}),"."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"thismonth--thisweek--thisquarter--thisyear",children:"ThisMonth / ThisWeek / ThisQuarter / ThisYear"}),"\n",(0,t.jsx)(n.p,{children:"Convenience factory methods for common ranges:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange month = range.ThisMonth();\nDateRange week = range.ThisWeek();\nDateRange quarter = range.ThisQuarter();\nDateRange year = range.ThisYear();\n"})}),"\n",(0,t.jsx)(n.h3,{id:"contains",children:"Contains"}),"\n",(0,t.jsx)(n.p,{children:"Check if a date or another range is fully contained:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"bool has = range.Contains(myRange, new DateTime(2025, 6, 15));\nbool sub = range.Contains(myRange, subRange);\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Signature:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"bool Contains(DateRange range, DateTime date)"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"bool Contains(DateRange range, DateRange other)"})}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"overlaps",children:"Overlaps"}),"\n",(0,t.jsx)(n.p,{children:"Check if two ranges overlap (share at least one day):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"bool overlapping = range.Overlaps(rangeA, rangeB);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"bool Overlaps(DateRange a, DateRange b)"})]}),"\n",(0,t.jsx)(n.h3,{id:"iscontainedby",children:"IsContainedBy"}),"\n",(0,t.jsx)(n.p,{children:"Check if the first range is entirely within the second:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"bool inside = range.IsContainedBy(inner, outer);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"bool IsContainedBy(DateRange range, DateRange container)"})]}),"\n",(0,t.jsx)(n.h3,{id:"intersection",children:"Intersection"}),"\n",(0,t.jsx)(n.p,{children:"Return the overlapping portion of two ranges (or an empty range if they don't overlap):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange overlap = range.Intersection(rangeA, rangeB);\n// \u2192 DateRange covering the shared days\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange Intersection(DateRange a, DateRange b)"})]}),"\n",(0,t.jsx)(n.h3,{id:"union",children:"Union"}),"\n",(0,t.jsx)(n.p,{children:"Merge two ranges into the smallest range that covers both (they do not need to overlap):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange merged = range.Union(rangeA, rangeB);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange Union(DateRange a, DateRange b)"})]}),"\n",(0,t.jsx)(n.h3,{id:"expand",children:"Expand"}),"\n",(0,t.jsx)(n.p,{children:"Extend a range by N units on one or both ends:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange expanded = range.Expand(myRange, 7, TimeUnit.Days);\n// Adds 7 days on each side\n\nDateRange expandedStart = range.Expand(myRange, 7, TimeUnit.Days, expandStart: true, expandEnd: false);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange Expand(DateRange range, int amount, TimeUnit unit, bool expandStart = true, bool expandEnd = true)"})]}),"\n",(0,t.jsx)(n.h3,{id:"shrink",children:"Shrink"}),"\n",(0,t.jsx)(n.p,{children:"Contract a range by N units from one or both ends:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange shrunk = range.Shrink(myRange, 1, TimeUnit.Weeks);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange Shrink(DateRange range, int amount, TimeUnit unit, bool shrinkStart = true, bool shrinkEnd = true)"})]}),"\n",(0,t.jsx)(n.h3,{id:"shift",children:"Shift"}),"\n",(0,t.jsx)(n.p,{children:"Move a range forward or backward in time:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"DateRange shifted = range.Shift(myRange, 1, TimeUnit.Months); // forward\nDateRange back = range.Shift(myRange, -2, TimeUnit.Weeks); // backward\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"DateRange Shift(DateRange range, int amount, TimeUnit unit)"})]}),"\n",(0,t.jsx)(n.h3,{id:"isadjacent",children:"IsAdjacent"}),"\n",(0,t.jsx)(n.p,{children:"Check if two ranges are adjacent (end of one is the day before start of the other):"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"bool adj = range.IsAdjacent(rangeA, rangeB);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"bool IsAdjacent(DateRange a, DateRange b)"})]}),"\n",(0,t.jsx)(n.h3,{id:"merge",children:"Merge"}),"\n",(0,t.jsx)(n.p,{children:"Merge a collection of overlapping or adjacent ranges into minimal non-overlapping ranges:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"IEnumerable<DateRange> merged = range.Merge(listOfRanges);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"IEnumerable<DateRange> Merge(IEnumerable<DateRange> ranges)"})]}),"\n",(0,t.jsx)(n.h3,{id:"gaps",children:"Gaps"}),"\n",(0,t.jsx)(n.p,{children:"Return ranges representing gaps between a sorted list of ranges, bounded by a container range:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"var container = range.Create(new DateTime(2025, 1, 1), new DateTime(2025, 12, 31));\nIEnumerable<DateRange> gaps = range.Gaps(listOfRanges, container);\n// \u2192 Ranges for periods within the container not covered by any input range\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"IEnumerable<DateRange> Gaps(IEnumerable<DateRange> ranges, DateRange container)"})]}),"\n",(0,t.jsxs)(n.p,{children:["The ",(0,t.jsx)(n.code,{children:"container"})," parameter defines the bounding range within which gaps are calculated. Only uncovered periods that fall inside ",(0,t.jsx)(n.code,{children:"container"})," are returned."]}),"\n",(0,t.jsx)(n.h3,{id:"eachday--eachweek--eachmonth",children:"EachDay / EachWeek / EachMonth"}),"\n",(0,t.jsx)(n.p,{children:"Enumerate dates within the range at a given step:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"foreach (DateTime day in range.EachDay(myRange))\n Console.WriteLine(day);\n\nforeach (DateTime weekStart in range.EachWeek(myRange))\n Console.WriteLine(weekStart);\n\nforeach (DateTime monthStart in range.EachMonth(myRange))\n Console.WriteLine(monthStart);\n"})}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Signatures:"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"IEnumerable<DateTime> EachDay(DateRange range)"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"IEnumerable<DateTime> EachWeek(DateRange range)"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.code,{children:"IEnumerable<DateTime> EachMonth(DateRange range)"})}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"eachworkday",children:"EachWorkday"}),"\n",(0,t.jsx)(n.p,{children:"Enumerate only workdays (Mon\u2013Fri) within the range:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"foreach (DateTime workday in range.EachWorkday(myRange))\n Console.WriteLine(workday);\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Signature:"})," ",(0,t.jsx)(n.code,{children:"IEnumerable<DateTime> EachWorkday(DateRange range)"})]}),"\n",(0,t.jsx)(n.h3,{id:"splitbyday--splitbyweek--splitbymonth--splitbyquarter",children:"SplitByDay / SplitByWeek / SplitByMonth / SplitByQuarter"}),"\n",(0,t.jsx)(n.p,{children:"Split a range into sub-ranges:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:"IEnumerable<DateRange> days = range.SplitByDay(myRange);\nIEnumerable<DateRange> weeks = range.SplitByWeek(myRange);\nIEnumerable<DateRange> months = range.SplitByMonth(myRange);\nIEnumerable<DateRange> quarters = range.SplitByQuarter(myRange);\n"})}),"\n",(0,t.jsx)(n.h2,{id:"complete-example",children:"Complete Example"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-csharp",children:'public class ProjectAnalyzer(IValiRange range)\n{\n public void AnalyzeProject(DateTime projectStart, DateTime projectEnd)\n {\n var project = range.Create(projectStart, projectEnd);\n\n Console.WriteLine($"Duration: {project.TotalDays} days");\n\n // Split into monthly sprints\n var sprints = range.SplitByMonth(project).ToList();
1\n Console.WriteLine($"Sprints: {sprints.Count}");\n\n // Find holiday gaps (if holiday service available)\n var workdays = range.EachWorkday(project).Count();\n Console.WriteLine($"Workdays: {workdays}");\n\n // Compute Q-by-Q breakdown\n foreach (var quarter in range.SplitByQuarter(project))\n {\n Console.WriteLine($" {quarter.Start:MMM dd} \u2013 {quarter.End:MMM dd}: {quarter.TotalDays} days");\n }\n }\n}\n'})})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(o,{...e})}):o(e)}},8453(e,n,a){a.d(n,{R:()=>s,x:()=>l});var r=a(6540);const t={},i=r.createContext(t);function s(e){const n=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:s(e.components),r.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.