Find a range inside a range using LINQ - c#

I've a date list
StartDate EndDate
1-Nov-2011 31-Jan-2012
3-Mar-2012 1-Apr-2012
1-May-2012 31-Dec-2012
1-Jan-2013 1-Dec-2013
Get all the records which falls in this range
1-Jan-2012 31-Dec-2012
The answer would be the first three records from the above list
How could i do it using Linq.
Thanks

This should work:
var rangeStart = new DateTime(2012, 1, 1);
var rangeEnd = new DateTime(2012, 12, 31);
var res = list
.Where(item => (item.StartTime < rangeStart ? rangeStart : item.StartTime) < (item.EndTime < rangeEnd ? item.EndTime : rangeEnd) )
.ToList();
The condition is "the larger of the two left ends needs to be less than the smaller of the two right ends".

I Suggest the following wrapper
public struct DateInterval
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public bool HasIntersection(DateInterval secondInterval)
{
return HasIntersection(this.StartDate, this.EndDate,secondInterval.StartDate,secondInterval.EndDate);
}
private bool HasIntersection(DateTime dateStart1, DateTime dateEnd1, DateTime dateStart2, DateTime dateEnd2)
{
if (dateEnd1 < dateStart2) return false;
if (dateEnd2 < dateStart1) return false;
return true;
}
}
usage:
var targetInterval = new DateInterval() {StartDate = new DateTime(2012, 1, 1), EndDate = new DateTime(2012, 1, 1)};
var listOfIntervals =GetIntervals();//retrieve data
var filteredList = listOfIntervals.Where(targetInterval.HasIntersection).ToList();

Related

Find Gaps Between date ranges

I need your help. I'm trying to figure out how I can get find Gaps between EndDate and the next StartDate. If there is a Gap I need to return the values where the gap is. Can you please help me?
I have a list with StartDate and Enddate.
Example:
Startdate: 2/01/2021 Enddate: 2/10/2021
Startdate: 2/11/2021 Enddate: 2/15/2021
Startdate: 2/20/2021 Enddate: 2/25/2021
Between 1 and 2 is no Gap. Between 2 (Enddate) and 3 (Stardate) is a Gap and needs to return a result like this: Gap found between 2/16/2021 and 2/19/2021.
I already tried this one but it didn't work out for me well, may someone of you can help me here?
static void Main(string[] args)
{
List<DateRanges> DateRanges = new List<DateRanges>();
DateRanges.Add(new DateRanges() { StartDate = new DateTime(2021, 01, 01), EndDate = new DateTime(2021, 01, 31) });
DateRanges.Add(new DateRanges() { StartDate = new DateTime(2021, 02, 10), EndDate = new DateTime(2021, 02, 25) });
var missing = DateRangeEnumerable.GetDates(DateRanges);
var ranges = missing.GetRanges();
}
public class DateRanges
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
//public DateRanges(DateTime Start, DateTime End)
//{
// StartDate = Start;
// EndDate = End;
//}
}
public static class DateRangeEnumerable
{
public static IEnumerable<DateTime> GetDates(this IEnumerable<DateRanges> source)
{
var sortedSource = source.OrderBy(r => r.StartDate);
foreach (var range in sortedSource)
{
var d = range.StartDate;
while (d < range.EndDate)
{
yield return d;
d = d.AddDays(1);
}
}
}
public static IEnumerable<DateRanges> GetRanges(this IEnumerable<DateTime> source)
{
var sortedSource = source.OrderBy(d => d);
var enumerator = sortedSource.GetEnumerator();
if (!enumerator.MoveNext())
yield break;
DateTime from = enumerator.Current;
DateTime prev = from;
while (true)
{
while (true)
{
if (enumerator.MoveNext())
{
if (enumerator.Current == prev.AddDays(1))
prev = enumerator.Current;
else
break;
}
else
{
yield return new DateRanges() { StartDate = from, EndDate = prev.AddDays(1) };
yield break;
}
}
yield return new DateRanges() { StartDate = from, EndDate = prev.AddDays(1) };
from = enumerator.Current;
prev = enumerator.Current;
}
}
}
Exmaple
var dateRanges = new List<DateRanges>
{
new() {StartDate = new DateTime(2021, 2, 01), EndDate = new DateTime(2021, 2, 10)},
new() {StartDate = new DateTime(2021, 02, 11), EndDate = new DateTime(2021, 02, 15)},
new() {StartDate = new DateTime(2021, 02, 20), EndDate = new DateTime(2021, 02, 25)}
};
var end = dateRanges.First().EndDate;
foreach (var range in dateRanges.Skip(1))
{
if(end.AddDays(1) < range.StartDate )
Console.WriteLine($"{end.AddDays(1):d} - {range.StartDate.AddDays(-1):d}");
end = range.EndDate;
}
Output
16/02/2021 - 19/02/2021
Disclaimer : This contains no error checking, no sorting, nothing implied from your code, and assumes that dates have no time value. It merely just replicates your description
What about using a linked list ?
Code:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
internal static class Program
{
private static void Main(string[] args)
{
var ranges = new List<DateRange>();
ranges.Add(
new DateRange
{
StartDate = new DateTime(2021, 01, 01),
EndDate = new DateTime(2021, 01, 31)
}
);
ranges.Add(
new DateRange
{
StartDate = new DateTime(2021, 02, 10),
EndDate = new DateTime(2021, 02, 25)
}
);
var list = new LinkedList<DateRange>(ranges);
var gaps = new List<LinkedListNode<DateRange>>();
var current = list.First;
while (current != null)
{
var next = current.Next;
if (next != null && next.Value.StartDate > current.Value.EndDate)
gaps.Add(current);
current = next;
}
Console.WriteLine("Gaps found:");
foreach (var gap in gaps)
{
Console.WriteLine("---------------------------");
Console.WriteLine("Date Range 1:");
Console.WriteLine(gap.Value);
Console.WriteLine("Date Range 2:");
Console.WriteLine(gap.Next!.Value);
Console.WriteLine(
$"Gap length in minutes: {(gap.Next.Value.StartDate - gap.Value.EndDate).TotalMinutes}");
Console.WriteLine("---------------------------");
}
}
}
public class DateRange
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public override string ToString()
{
return $"{nameof(StartDate)}: {StartDate}, {nameof(EndDate)}: {EndDate}";
}
}
}
Result:
Gaps found:
---------------------------
Date Range 1:
StartDate: 1/1/2021 12:00:00 AM, EndDate: 1/31/2021 12:00:00 AM
Date Range 2:
StartDate: 2/10/2021 12:00:00 AM, EndDate: 2/25/2021 12:00:00 AM
Gap length in minutes: 14400
---------------------------
I like to use a generic extension method that returns subsequent item-pairs:
public static IEnumerable<(T Previous, T Next)> PreviousAndNext<T>(this IEnumerable<T> self)
{
using (var iter = self.GetEnumerator())
{
if (!iter.MoveNext())
yield break;
var previous = iter.Current;
while (iter.MoveNext())
{
var next = iter.Current;
yield return (previous, next);
previous = next;
}
}
}
This allow for a very compact linq query
DateRanges.PreviousAndNext()
.Where(p => p.Previous.EndDate.AddDays(1) < p.Next.StartDate)
.Select(p => (p.Previous.EndDate, p.Next.StartDate));
Well, you can enumerate the gaps like this:
private static IEnumerable<DateRanges> Gaps(IEnumerable<DateRanges> dates) {
var source = dates
.OrderBy(range => range.StartDate);
DateTime last = DateTime.MinValue;
bool first = true;
foreach (var range in source) {
if (!first && range.StartDate.AddDays(1) > last)
yield return new DateRanges() {
StartDate = last.AddDays(1),
EndDate = range.StartDate.AddDays(-1))
};
// In case of overlapping periods we have to pick the latest date
last = first || range.EndDate > last
? range.EndDate
: last;
first = false;
}
}
If you want to print them all you have to do is to loop:
foreach (var gap in Gaps(dateRanges))
Console.WriteLine($"Gap found between {gap.StartDate} and {gap.EndDate}");

How to find exact date range from list of date ranges by entering single date

I want to find the date range which falls in input date, following is structure
public class Duration
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
var durations = new List<Duration>();
var duration1 = new Duration()
{
StartDate = new DateTime(2017, 08, 1),
EndDate = new DateTime(2017, 08, 10)
};
durations.Add(duration1);
var duration2 = new Duration()
{
StartDate = new DateTime(2017, 08, 5),
EndDate = new DateTime(2017, 08, 10)
};
durations.Add(duration2);
var duration3 = new Duration()
{
StartDate = new DateTime(2017, 08, 5),
EndDate = new DateTime(2017, 08, 6)
};
durations.Add(duration3);
Now I want to find duration which is closest to the entered date for list of <Durations> with LINQ or for-loop
My expected result for currentDate=new DateTime(2017, 08, 7); is duration2
You first need to check if the currentDate is within the start and end dates of each range. For the ones that meet that condition, you calculate the "closeness" adding both distances. When you find one lapse(gap) smaller tan the previous, you save its index... and voilá
int lapse = Integer.MaxValue;
int counter = 0;
int index = 0;
foreach (d in durations) {
if (((d.StartDate <= currentDate) && (d.EndDate >= currentDate))) {
int newlapse = ((currentDate - d.StartDate).TotalDays + (d.EndDate - currentDate).TotalDays);
if ((newlapse < lapse)) {
lapse = newlapse;
index = counter;
}
}
counter +=1;
}
return durations(index);
If you need the middle of interval to be closest:
durations.OrderBy((d) => Math.Abs(d.EndDate.Ticks + d.StartDate.Ticks) / 2 - currentDate.Ticks).FirstOrDefault();
If you need the start of interval to be closest:
durations.OrderBy((d) => Math.Abs(d.EndDate.Ticks - currentDate.Ticks)).FirstOrDefault();
As D le mentioned above
First check if currentDate is within the start and end dates
Second select the duration with the minimal difference between start end end date
I used a nuget package called morelinq which gives nice extensions methods like MinBy:
var result = (from d in durations
where (d.StartDate <= currentDate && d.EndDate >= currentDate)
select d).MinBy(d => d.EndDate - d.StartDate);

Extract sub-periods within a period

Given a period starting from StartingDate to EndingDate.
I want to get the intervals within that period starting given StartingMonth and EndingMonth.
Example :
StartingMonth = april (4)
EndingMonth = november (11)
Periods :
Period A : StartingDate = (2014, 03, 01); EndingDate = (2015, 02, 28);
Period B : StartingDate = (2014, 07, 01); EndingDate = (2015, 06, 30);
Period C : StartingDate = (2014, 01, 01); EndingDate = (2015, 12, 31);
Would return :
Period A : 1 sub-period = (2014, 4, 1) - (2014, 11, 30)
Period B : 2 sub-periods = (2014, 7, 1) - (2014, 11, 30) ; (2015, 4, 1) - (2015, 6, 30)
Period C : 2 sub-periods = (2014, 4, 1) - (2014, 11, 30) ; (2015, 4, 1) - (2015, 11, 30)
I have tried this (seems to be the hard way and does not manage multiple sub-periods):
May be an easier way using LINQ ?
if (StartingDate.Month < startingMonth && EndingDate.Month < endingMonth)
{
periods.Add(new PeriodInterval
{
StartDate = new DateTime(StartingDate.Year, startingMonth, 1),
EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
});
}
if (StartingDate.Month > startingMonth && EndingDate.Month > endingMonth)
{
periods.Add(new PeriodInterval
{
StartDate = new DateTime(StartingDate.Year, startingMonth, 1),
EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
});
}
if (StartingDate.Month < startingMonth && EndingDate.Month > endingMonth)
{
periods.Add(new PeriodInterval
{
StartDate = new DateTime(StartingDate.Year, startingMonth, 1),
EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
});
}
if (StartingDate.Month > startingMonth && EndingDate.Month < endingMonth)
{
periods.Add(new PeriodInterval
{
StartDate = new DateTime(StartingDate.Year, startingMonth, 1),
EndDate = new DateTime(StartingDate.Year, endingMonth, EndingDate.Day)
});
}
The idea is to returns the blue periods within the red period :
class Discount
{
public int DiscountID { get; set; } //You will need some Key field if you are storing these in a database.
public DateTime issueDate { get; set; }
public DateTime expirationDate { get; set; }
public List<PeriodInterval> intervals { get; set; }
public Discount(DateTime IssueDate, DateTime ExpirationDate)
{
issueDate = IssueDate;
expirationDate = ExpirationDate;
intervals = new List<PeriodInterval>();
}
public void AddInterval(DateTime StartDate, DateTime EndDate)
{
intervals.Add(new PeriodInterval() {
StartMonth=StartDate.Month,
StartDay=StartDate.Day,
EndMonth=EndDate.Month,
EndDay=EndDate.Day
});
}
public List<Period> GetPeriods()
{
List<Period> periods=new List<Period>();
int yearCount = expirationDate.Year-issueDate.Year+1; //+1: Run at least one year against the periods.
for (int i = 0; i < yearCount; i++)
{
//Loop through all the years and add 'Periods' from all the PeriodInterval info.
foreach (PeriodInterval pi in intervals)
{
var period = pi.GetPeriod(issueDate, expirationDate, i);
if (period != null)
periods.Add(period);
}
}
return periods;
}
}
class Period
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
class PeriodInterval
{
public int PeriodIntervalID { get; set; } //You will need some Key field if you are storing these in a database.
public int DiscountID { get; set; } //Foreign Key to Discount. This is alsof for database storage.
public int StartMonth { get; set; }
public int StartDay { get; set; }
public int EndMonth { get; set; }
public int EndDay { get; set; }
public Period GetPeriod(DateTime issueDate, DateTime expirationDate, int Year)
{
DateTime PeriodStart = new DateTime(issueDate.AddYears(Year).Year, StartMonth, StartDay);
DateTime PeriodEnd = new DateTime(issueDate.AddYears(Year).Year, EndMonth, EndDay);
PeriodStart=new DateTime(Math.Max(PeriodStart.Ticks, issueDate.Ticks)); //Limit period to the max of the two start dates.
PeriodEnd = new DateTime(Math.Min(PeriodEnd.Ticks, expirationDate.Ticks)); //Limit period to the min of the two end dates.
if(PeriodEnd>PeriodStart) //If a valid period
{
return new Period()
{
StartDate = PeriodStart,
EndDate = PeriodEnd
};
}
//Default Return Null
return null;
}
}
I built a console application to test this out:
static void Main(string[] args)
{
List<Discount> Discounts = new List<Discount>();
Discount d1 = new Discount(new DateTime(2014, 3, 1), new DateTime(2015, 02, 28));
Discount d2 = new Discount(new DateTime(2014, 7, 1), new DateTime(2015, 06, 30));
Discount d3 = new Discount(new DateTime(2014, 01, 1), new DateTime(2015, 12, 31));
Discounts.Add(d1);
Discounts.Add(d2);
Discounts.Add(d3);
foreach (Discount d in Discounts)
{
d.AddInterval(new DateTime(2014, 4, 1), new DateTime(2014, 11, 30));
Console.WriteLine("IssueDate:{0} ExpirationDate:{1}", d.issueDate, d.expirationDate);
foreach (Period p in d.GetPeriods())
{
Console.WriteLine("Start:{0} End:{1}", p.StartDate, p.EndDate);
}
}
Console.ReadLine();
}
Here's what that prints out:
You can use the Time Period Library for .NET:
// ----------------------------------------------------------------------
public void ExtractSubPeriods()
{
foreach ( ITimePeriod subPeriod in GetSubPeriods(
new TimeRange( new DateTime( 2014, 4, 1 ), new DateTime( 2015, 2, 28 ) ) ) )
{
Console.WriteLine( "SubPeriods 1: {0}", subPeriod );
foreach ( ITimePeriod subPeriod in GetSubPeriods(
new TimeRange( new DateTime( 2014, 7, 1 ), new DateTime( 2015, 6, 30 ) ) ) )
{
Console.WriteLine( "SubPeriods 2: {0}", subPeriod );
}
foreach ( ITimePeriod subPeriod in GetSubPeriods(
new TimeRange( new DateTime( 2014, 4, 1 ), new DateTime( 2015, 12, 31 ) ) ) )
{
Console.WriteLine( "SubPeriods 3: {0}", subPeriod );
}
} // ExtractSubPeriods
// ----------------------------------------------------------------------
public ITimePeriodCollection GetSubPeriods( ITimeRange timeRange )
{
ITimePeriodCollection periods = new TimePeriodCollection();
periods.Add( timeRange );
int startYear = periods.Start.Year;
int endYear = periods.End.Year + 1;
for ( int year = startYear; year <= endYear; year++ )
{
periods.Add( new TimeRange( new DateTime( year, 4, 1 ), new DateTime( year, 12, 1 ) ) );
}
TimePeriodIntersector<TimeRange> intersector = new TimePeriodIntersector<TimeRange>();
return intersector.IntersectPeriods( periods );
} // GetSubPeriods
A few things to consider:
As humans, we typically use fully-inclusive ranges for date-only values, while we use half-open intervals for time-only or date+time values. Think: 2 days from Jan 1 to Jan 2, but 1 hour from 1:00 to 2:00, or from Jan 1 Midnight to Jan 2 Midnight.
.Net's built-in DateTime type, is a date+time type. When you omit the time, it uses midnight. You cannot remove the time portion.
If you were to use DateTime with date-at-midnight ranges, the best you could do is choose to ignore the time portion. That makes for some tricky code, as you would have to normalize your inputs to midnight before comparing against the range. I don't recommend this approach, as it is error prone. The edge cases will pile up quickly.
Therefore, I recommend either switching to half-open intervals with DateTime, or if you need to continue to use fully-inclusive ranges then consider using the LocalDate type from Noda Time. I will show you examples of both.
Because you are accepting month numbers as inputs, consider that you should also handle the case of them being out of sequence. That is, a two-month sub-period may range from December of one year, to January of the next.
Unless there are guarantees that the outer period will fall exactly at the start and end points of a whole month, you will need to trim the results. For example, if your Period ran from Jan 3 2014 to March 9 2016, then the subperiod in 2015 would have the whole months, but 2014 would be trimmed at the start and 2016 would be trimmed at the end.
Here is how you can achieve this using DateTime and half-open date-at-midnight intervals:
public class DateTimeInterval
{
/// <summary>
/// The date and time that the interval starts.
/// The interval includes this exact value.
/// </summary>
public DateTime StartDate { get; private set; }
/// <summary>
/// The date and time that the interval is over.
/// The interval excludes this exact value.
/// </summary>
public DateTime EndDate { get; private set; }
public DateTimeInterval(DateTime startDate, DateTime endDate)
{
StartDate = startDate;
EndDate = endDate;
}
public IEnumerable<DateTimeInterval> GetSubIntervals(int startingMonth,
int endingMonth)
{
// Determine the possible ranges based on the year of this interval
// and the months provided
var ranges = Enumerable.Range(StartDate.Year,
EndDate.Year - StartDate.Year + 1)
.Select(year => new DateTimeInterval(
new DateTime(year, startingMonth, 1),
new DateTime(
startingMonth > endingMonth ? year + 1 : year,
endingMonth, 1)
.AddMonths(1)));
// Get the ranges that are overlapping with this interval
var results = ranges.Where(p => p.StartDate < this.EndDate &&
p.EndDate > this.StartDate)
.ToArray();
// Trim the edges to constrain the results to this interval
if (results.Length > 0)
{
if (results[0].StartDate < this.StartDate)
{
results[0] = new DateTimeInterval(
this.StartDate,
results[0].EndDate);
}
if (results[results.Length - 1].EndDate > this.EndDate)
{
results[results.Length - 1] = new DateTimeInterval(
results[results.Length - 1].StartDate,
this.EndDate);
}
}
return results;
}
}
Using the above code:
var interval = new DateTimeInterval(new DateTime(2014, 3, 1), // inclusive
new DateTime(2015, 3, 1)); // exclusive
var subIntervals = interval.GetSubIntervals(4, 11);
And here is how you can achieve the same thing using NodaTime.LocalDate and fully-inclusive date-only intervals:
using NodaTime;
public class LocalDateInterval
{
/// <summary>
/// The date that the interval starts.
/// The interval includes this exact value.
/// </summary>
public LocalDate StartDate { get; private set; }
/// <summary>
/// The date that the interval ends.
/// The interval includes this exact value.
/// </summary>
public LocalDate EndDate { get; private set; }
public LocalDateInterval(LocalDate startDate, LocalDate endDate)
{
StartDate = startDate;
EndDate = endDate;
}
public IEnumerable<LocalDateInterval> GetSubIntervals(int startingMonth,
int endingMonth)
{
// Determine the possible ranges based on the year of this interval
// and the months provided
var ranges = Enumerable.Range(StartDate.Year,
EndDate.Year - StartDate.Year + 1)
.Select(year => new LocalDateInterval(
new LocalDate(year, startingMonth, 1),
new LocalDate(
startingMonth > endingMonth ? year + 1 : year,
endingMonth, 1)
.PlusMonths(1).PlusDays(-1)));
// Get the ranges that are overlapping with this interval
var results = ranges.Where(p => p.StartDate <= this.EndDate &&
p.EndDate >= this.StartDate)
.ToArray();
// Trim the edges to constrain the results to this interval
if (results.Length > 0)
{
if (results[0].StartDate < this.StartDate)
{
results[0] = new LocalDateInterval(
this.StartDate,
results[0].EndDate);
}
if (results[results.Length - 1].EndDate > this.EndDate)
{
results[results.Length - 1] = new LocalDateInterval(
results[results.Length - 1].StartDate,
this.EndDate);
}
}
return results;
}
}
Using the above code:
var interval = new LocalDateInterval(new LocalDate(2014, 3, 1), // inclusive
new LocalDate(2015, 2, 28)); // inclusive
var subIntervals = interval.GetSubIntervals(4, 11);
This shoud work:
var periods = Periods
.Select(p => new {
p = p,
a = p.StartingDate.Year*12 + p.StartingDate.Month - 1,
b = p.EndingDate.Year*12 + p.EndingDate.Month
}
)
.Select(x => new {
period = x.p,
subperiods =
Enumerable
.Range(x.a, x.b - x.a)
.Select(e => new DateTime(e/12, e%12 + 1, 1))
.Where(d => StartingMonth <= d.Month && d.Month <= EndingMonth)
.GroupBy(i => i.Year)
.Where(g => g.Count() > 1)
.Select(g => new Period {
StartingDate = g.Min(),
EndingDate = g.Max()
})
.Select(p => new Period {
StartingDate = p.StartingDate < x.p.StartingDate ? x.p.StartingDate : p.StartingDate,
EndingDate = (p.EndingDate > x.p.EndingDate ? x.p.EndingDate : p.EndingDate)
.AddMonths(1)
.AddDays(-1)
})
});
UPDATE
According to your image, this would do the trick:
var periods = Periods
.Select(p => new {
p = p,
a = p.StartingDate.Year*12 + p.StartingDate.Month - 1,
b = p.EndingDate.Year*12 + p.EndingDate.Month
}
)
.Select(x => new {
period = x.p,
subperiods =
Enumerable
.Range(x.a, x.b - x.a)
.Select(e => new DateTime(e/12, e%12 + 1, 1))
.Where(d => StartingMonth <= d.Month && d.Month <= EndingMonth)
.GroupBy(i => i.Year)
.Where(g => g.Count() > 1)
.Select(g => g.Select(i => i))
});

Need the sequence Order of Quarters of FY2011-12 based on a date given as input

ASP.NET using C#
The following are the Quarters for the financial year 2011-12
April 2011 to June2011 - Q1
July2011 to Sep2011 - Q2
Oct2011 to Dec2011 - Q3
Jan2012 to March 2012 - Q4
EDIT:
If i give a date as input then i need the output interms of the Quarter of that month:
Lets consider a date as input is 02-Jan-2012.
then i need the output as Q4
Lets take another date as input: 31May2012.
For this i need the output as Q1
Please help!!
Here is the function
public string GetQuarter(DateTime date)
{
// we just need to check the month irrespective of the other parts(year, day)
// so we will have all the dates with year part common
DateTime dummyDate = new DateTime(1900, date.Month, date.Day);
if (dummyDate < new DateTime(1900, 7, 1) && dummyDate >= new DateTime(1900, 4, 1))
{
return "Q1";
}
else if (dummyDate < new DateTime(1900, 10, 1) && dummyDate >= new DateTime(1900, 7, 1))
{
return "Q2";
}
else if (dummyDate < new DateTime(1900, 1, 1) && dummyDate >= new DateTime(1900, 10, 1))
{
return "Q3";
}
else
{
return "Q4";
}
}
Hope this could help.
static void Main(string[] args)
{
List<DateRange> range = new List<DateRange>();
//temp filling the data
DateTime start = new DateTime(2011, 4, 1);
range.Add(new DateRange() {From=start,To = start.AddMonths(3).AddMilliseconds(-1),Name="Q1"});
start = range.LastOrDefault().To.AddMilliseconds(1);
range.Add(new DateRange() { From = start, To = start.AddMonths(3).AddMilliseconds(-1), Name = "Q2" });
start = range.LastOrDefault().To.AddMilliseconds(1);
range.Add(new DateRange() { From = start, To = start.AddMonths(3).AddMilliseconds(-1), Name = "Q3" });
start = range.LastOrDefault().To.AddMilliseconds(1);
range.Add(new DateRange() { From = start, To = start.AddMonths(3).AddMilliseconds(-1), Name = "Q4" });
var order = range.OrderByDescending(r => r.IsCurrentQuater(DateTime.Now));
foreach (var itm in order)
Console.WriteLine(itm);
}
}
public class DateRange
{
public string Name { get; set; }
public DateTime From { get; set; }
public DateTime To { get; set; }
public bool IsCurrentQuater(DateTime date)
{
return date >= From && date <= To;
}
public override string ToString()
{
return string.Format("{0} - {1} to {2}", Name, From, To);
}
}
Regards.

Multiple date diff//C#

How to calculate a multiple date difference like
startDate1=("dd-MM-yy") 20-08-2011
endDate1=25-08-11
another
startdate2=27-08-2011
endDate2=30-08-2011
such that output will be
(endDate1-startDate1)+(endDate2-StartDate2) == 8days //only in terms of days
Use TimeSpan to calculate date difference.
Eg:
TimeSpan ts = Date1 - Date2;
int numberOfDays = ts.Days;
More info can be found here
Date - or + Date will return TimeSpan, it has a property named "Days" is what you need.
((endDate1-startDate)+(endDate2-StartDate2)).Days
Try this code :-
DateTime d1 = StarDate
DateTime d2 = EndDate;
TimeSpan t1 = d2.Subtract(d1);
days = t1.Days;
hours = t1.Hours;
Try this,
DateTime strdate = Convert.ToDateTime("1/1/2011");
DateTime enddate = Convert.ToDateTime("1/10/2011");
DateTime strdate1 = Convert.ToDateTime("1/1/2011");
DateTime enddate1 = Convert.ToDateTime("1/10/2011");
int resultdays = (enddate.Subtract(strdate) + enddate1.Subtract(strdate1)).Days;
Complete Code/Answer....
public class DateController : Controller
{
public ActionResult date()
{
int allDiff;
List<int> list=new List<int>();
int flag = 0;
int conflict = 0;
List<int> conf = new List<int>();
conf.Add(0);
int a = 0;
DateTime[] startDate = new DateTime[3];
startDate[0] = new DateTime(2011, 11, 5);
startDate[1] = new DateTime(2011, 11,7);
startDate[2] = new DateTime(2011, 11, 15);
DateTime[] endDate = new DateTime[3];
endDate[0] = new DateTime(2011, 11, 10);
endDate[1] = new DateTime(2011, 11,12);
endDate[2] = new DateTime(2011, 11, 20);
DateTime Min= startDate.Min();
DateTime Max = endDate.Max();
TimeSpan span = Max - Min;
int total = span.Days;
ViewBag.globalTotal = total;
foreach (DateTime e in endDate)
{
foreach (DateTime s in startDate)
{
if (s >= e)
{
TimeSpan span1 = s - e;
allDiff = span1.Days;
list.Add(allDiff);
flag = 1;
conflict = 1;
}
else {
flag = 0;
}
}
if((list.Count==1)&&(conflict==1)&&(list!=null)){
a = list[0];
conf.Add(a);
}
if ((flag == 1)&&(list.Count>1))
{
int m = list.Min();
ViewBag.dhiraj = m;
total = total - m;
list.Clear();
}
}
int confl= conf.Min();
total=total-confl;
ViewBag.Total = total;
return View();
}
}
`
If you want the exact DateDiff function as it works in SQL, you can remove time stamp of the Date variables and then Subtract one from another. It will give u exact number of days.
Ex.
DateTime dt = DateTime.Parse(fromDate.ToShortDateString());
DateTime dt1 = DateTime.Parse(toDate.ToShortDateString());
int noOfDays = dt.Subtract(dt1).TotalDays;

Categories