How can I get a collection of months between two Dates? - c#

Below is my code. I am only getting the difference between two dates, but I want the name of that month which comes between the from and to dates.
public static int GetMonthsBetween(DateTime from, DateTime to)
{
if (from > to) return GetMonthsBetween(to, from);
var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));
if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
{
return monthDiff - 1;
}
else
{
return monthDiff;
}
}

Based on your code you could substract the month difference from the "to" DateTime to get DateTime difference from your input.
public static List<DateTime> GetMonthsBetween(DateTime from, DateTime to)
{
if (from > to) return GetMonthsBetween(to, from);
var monthDiff = Math.Abs((to.Year * 12 + (to.Month - 1)) - (from.Year * 12 + (from.Month - 1)));
if (from.AddMonths(monthDiff) > to || to.Day < from.Day)
{
monthDiff -= 1;
}
List<DateTime> results = new List<DateTime>();
for (int i = monthDiff; i >= 1; i--)
{
results.Add(to.AddMonths(-i));
}
return results;
}
To get the name of the month just format the DateTime to "MMM".
var dts = GetMonthsBetween(DateTime.Today, DateTime.Today.AddMonths(5));
foreach (var dateTime in dts)
{
Console.WriteLine(dateTime.ToString("MMM"));
}

If you want the names of all months between two dates, use something like this:
var d1 = new DateTime(2015,6,1);
var d2 = new DateTime(2015,9,1);
var monthlist = new List<string>();
string format = d1.Year == d2.Year ? "MMMM" : "MMMM yyyy";
for (var d = d1; d <= d2; d = d.AddMonths(1))
{
monthlist.Add(d.ToString(format));
}
The full list is now in monthlist - you will want to return that from your method.

Assuming you're using Java and JodaTime there are several flaws in your code.
You cant use from > to to evaluate if a date is after an other. Use from.isAfter(to) instead.
JodaTime already supplies a method to calculate the amount of whole months between two given Dates Months.monthsBetween(start,end).
With the calculated month difference you can instantiate a new DateTime object that holds a date in your desired month and output its name via yourNewDateTimeObject.month().getAsText().
edit: Just found out you're using C# so ignore my text above this. Below here I will try to answer your question in C#.
Why dont you just subtract the from from the to date and obtain your difference?
The resulting TimeSpan can be used to determine the amount of whole months between your two given dates.
To obtain the resulting month name you could use yourDateTime.ToString("MMMM");

Related

How to display all Fridays Date between two dates

How to get a Friday date from the given start date and end date,
For Example:
25/03/2021 - starting date
14/08/2021 - endind date
I have a class
public static class DateUtils
{
public static List<DateTime> GetWeekdayInRange(this DateTime from, DateTime to, DayOfWeek day)
{
const int daysInWeek = 7;
var result = new List<DateTime>();
var daysToAdd = ((int)day - (int)from.DayOfWeek + daysInWeek) % daysInWeek;
do
{
from = from.AddDays(daysToAdd);
result.Add(from);
daysToAdd = daysInWeek;
}
while (from < to);
return result;
}
}
That is how i call it in main method:
var from = DateTime.Today; // 25/8/2019
var to = DateTime.Today.AddDays(23); // 23/9/2019
var allFriday = from.GetWeekdayInRange(to, DayOfWeek.Friday);
Console.WriteLine(allFriday);
Console.ReadKey();
Error i get:
System.Collections.Generic.List`1[System.DateTime]
I am new and still learning, how do I call in the main method so that my output be like all dates(fridays) between the range?
Link I followed
To Answer your question, instead of printing allFridays in one go, iterate over each element of list i.e allFridays, convert into string and then print
foreach(var friday in allFridays)
Console.WriteLine(friday);
Why you are getting System.Collections.Generic.List[System.DateTime] ?
Console.WriteLine(), for non primitive type by default calls
.ToString() function which prints type of it(if it is not overridden). In your case, you
need an individual date not a type of List, so you need to iterate
each DateTime from the list and print each date.
One Liner solution:
Console.WriteLine(string.Join(Environment.NewLine, allFridays));
Alternate solution:
public static List<DateTime> GetWeekdayInRange(this DateTime #from, DateTime to, DayOfWeek day)
{
//Create list of DateTime to store range of dates
var dates = new List<DateTime>();
//Iterate over each DateTime and store it in dates list
for (var dt = #from; dt <= to; dt = dt.AddDays(1))
dates.Add(dt);
//Filter date based on DayOfWeek
var filteredDates = dates.Where(x => x.DayOfWeek == day).ToList();
return filteredDates;
}
...
var #from = DateTime.Today; // 25/8/2019
var to = DateTime.Today.AddDays(23); // 23/9/2019
var allFriday = #from.GetWeekdayInRange(to, DayOfWeek.Friday);
Console.WriteLine(string.Join(Environment.NewLine, allFridays));
.NET FIDDLE
Since in your Usage section, you have successfully get the result via GetWeekdayInRange. You can print the dates with these methods:
Method 1:
allFriday.ForEach(x => Console.WriteLine(x.ToShortDateString()));
Method 2:
foreach (var friday in allFriday)
{
Console.WriteLine(friday.ToShortDateString());
}
Method 3:
for (var i = 0; i < allFriday.Count(); i++)
{
Console.WriteLine(allFriday[i].ToShortDateString());
}
Note: ToShortDateString() is one of the methods to display Date string. You can define your desired Date pattern with ToString().

Finding the month between a range

I have a datasource that returns dates and I have to find where the months falls within the month and day range buckets. The months and day range buckets are predefined so I put it in a Dictionary (not sure if that is even a good idea). I am using linq to find the min and Max dates and extracting the month from them. I need to find month from the dictionary where that month extracted falls within the range. For Example
Dictionary<int, int> MonthDayBuckets = new Dictionary<int, int>() { { 3,31 }, { 6,30 }, { 9,30 }, { 12,31 } };
var MinyDate = _dataSource.Min(x => x.values[0]);
var MaxDate = _dataSource.Max(x => x.values[0]);
var startMonth = Convert.ToDateTime(MinyDate).ToString("MM");
var endMonth = Convert.ToDateTime(MaxDate).ToString("MM");
Say startmonth return Jan so I want to be able to go to the dictionary and return only march (03.31) and if I get 10 for the Max (October) I am trying to return (12,31) December
If my understanding is correct, your MonthDayBuckets variable is meant to represent date ranges:
3/31 - 6/30
6/30 - 9/30
9/30 - 12/31
12/31 - 3/31
...and given a month, you're wanting to see what the end date is of the interval that the first of that month falls between? Like you gave the example of October returning 12/31.
This problem can be simplified since you'll get the same result saying "what's the next occurring date after this given date?" The next occurring date for 10/01 would be 12/31. So here's how you could rearrange your data:
var availableDates = new List<string> { "03/31", "06/30", "09/30", "12/31" };
Now you'll be able to find a match by finding the index of the first one that's greater than your given date. Note how I made the month/day combos lexicographical orderable.
var startMonth = Convert.ToDateTime(MinyDate).ToString("MM");
var startDate = startMonth + "/01";
var endMonth = Convert.ToDateTime(MaxDate).ToString("MM");
var endDate = endMonth + "/01";
// Wrap around to the first date if this falls after the end
var nextStartDate = availableDates.FirstOrDefault(d => d.CompareTo(startDate) >= 1) ?? availableDates[0];
var nextEndDate = availableDates.FirstOrDefault(d => d.CompareTo(endDate) >= 1) ?? availableDates[0];
You could use Linq for the purpose. For example,
var nearestKey = MonthDayBuckets.Keys.Where(x => x >= endMonth.Month).Min();
var nearestDate = new DateTime(DateTime.Now.Year,nearestKey,MonthDayBuckets[nearestKey]); // or whatever the year it needs to be represent
Though above query would get you the result, I would suggest you define a structure to store the Range itself, rather than using Dictionary
For example,
public class Range
{
public MonthDate StartRange{get;set;}
public MonthDate EndRange{get;set;}
public Range(MonthDate startRange,MonthDate endRange)
{
StartRange = startRange;
EndRange = endRange;
}
}
public class MonthDate
{
public MonthDate(int month,int date)
{
Month = month;
Date = date;
}
public int Month{get;set;}
public int Date{get;set;}
//Depending on if your Ranges are inclusive or not,you need to decide how to compare
public static bool operator >=(MonthDate source, MonthDate comparer)
{
return source.Month>= comparer.Month && source.Date>=comparer.Date;
}
public static bool operator <=(MonthDate source, MonthDate comparer)
{
return source.Month<= comparer.Month && source.Date<=comparer.Date;
}
}
Now you could define ranges as
var dateRanges = new Range[]
{
new Range(new MonthDate(12,31),new MonthDate(3,31)),
new Range(new MonthDate(3,31),new MonthDate(6,30)),
new Range(new MonthDate(6,30),new MonthDate(12,31)),
};
var result = dateRanges.First(x=>x.StartRange <= new MonthDate(endMonth.Month,endMonth.Day) && x.EndRange >= new MonthDate(endMonth.Month,endMonth.Day));

Get date of last seven days

I want to get date of last seven days from now.For example current date is
02-10-2016, get date of seven days like this
01-10-2016,30-09-2016,29-09-2016,28-09-2016,27-09-2016,26-09-2016
My code
string dt = DateTime.Now.ToString("yyyy-MM-dd");
DateTime lastWeek = dt.AddDays(-7.0);
AddDays is a part of DateTime, not of string.
You need to build your dates iteratively and then convert it to a string.
DateTime[] last7Days = Enumerable.Range(0, 7)
.Select(i => DateTime.Now.Date.AddDays(-i))
.ToArray();
foreach (var day in last7Days)
Console.WriteLine($"{day:yyyy-MM-dd}"); // Any manipulations with days go here
Without LINQ, with a simple loop:
DateTime dt = DateTime.Now;
for (int i=0;i<7;i++)
{
dt = dt.AddDays(-1);
Console.WriteLine(dt.Date.ToShortDateString());
}
Try using Linq:
var date = new DateTime(2016, 10, 2);
var result = Enumerable.Range(1, 7)
.Select(day => date.Date.AddDays(- day))
.ToArray(); // if you want to represent dates as an array
Test
// 01-10-2016,30-09-2016,29-09-2016,28-09-2016,27-09-2016,26-09-2016,25-09-2016
Console.Write(string.Join(",", result.Select(d => d.ToString("dd-MM-yyyy"))));
You are almost there, the AddDays method will add only a specific number of days to the given data and dives you the resulted date. But here in your case you need a list of dates, so you have to loop through those dates and get them as well. I hope the following method will help you to do this:
public static string GetLast7DateString()
{
DateTime currentDate = DateTime.Now;
return String.Join(",",Enumerable.Range(0, 7)
.Select(x => currentDate.AddDays(-x).ToString("dd-MM-yyyy"))
.ToList());
}
Note : If you want to exclude the current date means you have to take the range from 7 and the count should be 7. You can read more about Enumerable.Range here
If you call this method like the following means you will get the output as 24-10-2016,23-10-2016,22-10-2016,21-10-2016,20-10-2016,19-10-2016,18-10-2016
string opLast7Days = GetLast7DateString();
public static List<DateTime> getLastSevenDate(DateTime currentDate)
{
List<DateTime> lastSevenDate = new List<DateTime>();
for (int i = 1; i <= 7; i++)
{
lastSevenDate.Add(currentDate.AddDays(-i));
}
return lastSevenDate;
}

c# months and years between given dates

I try to popup a msgbox that shows the months and years of the given dates for example
my input is:
7/2012 and 2/2013
and the output should be:
7/2012,8/2012,9/2012,10/2012,11/2012,12/2012,1/2013,2/2013
I wrote:
string datePart1;
string datePart2;
string[] date1 = new string[] { "" };
string[] date2 = new string[] { "" };
private void button1_Click(object sender, EventArgs e)
{
DateTime endDate = new DateTime(2013, 2, 1); // i will be having the date time as a variable from a textbox
DateTime begDate = new DateTime(2012, 7, 1); // i will be having the date time as a variable from a text box
int year, month;
if (endDate.Month - begDate.Month < 0)
{
month = (endDate.Month - begDate.Month) + 12;
endDate = new DateTime(endDate.Year - 1, endDate.Month, endDate.Day);
}
else
month = endDate.Month - begDate.Month;
year = endDate.Year - begDate.Year;
The above code calculates the time difference, but my attempts at outputting haven't worked.
Here's a sample to get you started.
It provides a handy MonthsInRange() method which returns a sequence of all the months in the specified range. You can then format the returned dates using "M\\/yyyy" (see below) to output the required format. (Note: That's not a letter V, it's a backslash followed by a forward slash!)
See Custom Date and Time Format Strings for an explanation of the format string.
using System;
using System.Collections.Generic;
namespace Demo
{
public static class Program
{
static void Main(string[] args)
{
DateTime endDate = new DateTime(2013, 2, 1);
DateTime begDate = new DateTime(2012, 7, 1);
foreach (DateTime date in MonthsInRange(begDate, endDate))
{
Console.WriteLine(date.ToString("M\\/yyyy"));
}
}
public static IEnumerable<DateTime> MonthsInRange(DateTime start, DateTime end)
{
for (DateTime date = start; date <= end; date = date.AddMonths(1))
{
yield return date;
}
}
}
}
Why "M\\/yyyy" and not just "M/yyyy"?
This is because the "/" character in a DateTime format string will be interpreted as the "date separator", not a literal "/". In some locales, this will come out as "." and not "/".
To fix this, we need to escape it with a "\" character. However, we can't just use a single "\" because C# itself will interpret that as an escape character, and will use it to escape the following character. The C# escape sequence for a literal "\" is "\\", which is why we have to put "\\/" and not just "\/".
Alternatively you can turn of escaping of "\" characters by prefixing the string with an # character, like so:
#"M/yyyy"
You can use whichever you prefer.
Since you're not guaranteed to have dates with the same day, you can use this code which creates new dates that only consider the first of the month.
static IEnumerable<string> InclusiveMonths(DateTime start, DateTime end)
{
// copies to ensure the same day.
var startMonth = new DateTime(start.Year, start.Month, 1);
var endMonth = new DateTime(end.Year, end.Month, 1);
for (var current = startMonth; current <= endMonth; current = current.AddMonths(1))
yield return current.ToString("M/yyyy");
}
// usage
foreach (var mmyyyy in InclusiveMonths(begDate, endDate))
{
Console.WriteLine(mmyyyy);
}
var allMonths = string.Join(", ", InclusiveMonths(begDate, endDate));
Look into using the TimeSpan structure, it'll help you achieve your goal a lot faster.
http://msdn.microsoft.com/en-us/library/system.timespan.aspx
You may use
TimeSpan dateDifference = endDate - begDate;
year = dateDifference.Days / 365;
month = dateDifference.Days / 30;
Edit:
I forgot TimeSpan does not feature Year or Month, sorry :(

Count of days intersecting between two date ranges

Would anyone have any ideas of how to best calculate the amount of days that intersect between two date ranges?
Here's a little method I wrote to calculate this.
private static int inclusiveDays(DateTime s1, DateTime e1, DateTime s2, DateTime e2)
{
// If they don't intersect return 0.
if (!(s1 <= e2 && e1 >= s2))
{
return 0;
}
// Take the highest start date and the lowest end date.
DateTime start = s1 > s2 ? s1 : s2;
DateTime end = e1 > e2 ? e2 : e1;
// Add one to the time range since its inclusive.
return (int)(end - start).TotalDays + 1;
}
Obtain a new range, defined by the later of the beginnings and the earlier of the ends, and determine the number of days since the beginning of the epoch for each day in that new range.
The difference is the number of days in the intersection. Accept only positive values.
Edited to take into account ranges instead of individual dates.
Here is an example from R. That might clarify the answer.
c_st = as.POSIXct("1996-10-14")
c_ed = as.POSIXct("1996-10-19")
d_st = as.POSIXct("1996-10-17")
d_ed = as.POSIXct("1999-10-22")
max(range(c_st,c_ed ))-min(range(d_st,d_ed) ) >= 0 & min(range(c_st,c_ed )) < max(range(d_st,d_ed) )
True would indicate that they intersect, False otherwise.
[r]
If I understand your question, you're asking for the number of days that overlap two date ranges, such as:
Range 1 = 2010-1-1 to 2010-2-1
Range 2 = 2010-1-5 to 2010-2-5
in this example the number of intersecting days would be 28 days.
Here is a code sample for that example
DateTime rs1 = new DateTime(2010, 1, 1);
DateTime re1 = new DateTime(2010, 2, 1);
DateTime rs2 = new DateTime(2010, 1, 5);
DateTime re2 = new DateTime(2010, 2, 5);
TimeSpan d = new TimeSpan(Math.Max(Math.Min(re1.Ticks, re2.Ticks) - Math.Max(rs1.Ticks, rs2.Ticks) + TimeSpan.TicksPerDay, 0));
The question asks between two date Ranges not two Dates. (Edited in response to comments)
So if you have 2 Date Ranges (r1s,r1e), you need to determine which starts first, Is there overlap, and what is the overlap.
double overlap(DateTime r1s, DateTime r1e, DateTime r2s, DateTime r1e){
DateTime t1s,t1e,t2s,t2e;
if (rs1<rs2) //Determine which range starts first
{
t1s = r1s;
t1e = r1e;
t2s = r2s;
t2e = r2e;
}
else
}
t1s = r2s;
t1e = r2e;
t2s = r1s;
t2e = r1e;
}
if (t1e<t2s) //No Overlap
{
return -1;
}
if (t1e<t2e) //Partial Overlap
}
TimeSpan diff = new TimeSpan(t1e.Ticks - t2s.Ticks);
{
else //Range 2 totally withing Range 1
}
TimeSpan diff = new TimeSpan(t2e.Ticks - t2s.Ticks);
{
double daysDiff = diff.TotalDays;
return daysDiff;
}

Categories