This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How do I loop through a date range?
Is there a way to make a foreach loop for each day in a specific month?
thinking of something like
foreach (DateTime date in DateTime.DaysInMonth(2012, 1))
{
}
You can write a helper method pretty easily:
public static IEnumerable<DateTime> AllDatesInMonth(int year, int month)
{
int days = DateTime.DaysInMonth(year, month);
for (int day = 1; day <= days; day++)
{
yield return new DateTime(year, month, day);
}
}
Then call it with:
foreach (DateTime date in AllDatesInMonth(2012, 1))
This is probably overkill for something you're only doing once, but it's much nicer than using a for loop or something similar if you're doing this a lot. It makes your code say just what you want to achieve, rather than the mechanics for how you're doing it.
Try using a for loop instead.
for (int i = 1; i <= DateTime.DaysInMonth(year, month); i++)
{
DateTime dt = new DateTime(year, month, i);
}
You can use Range:
Enumerable
.Range(1, DateTime.DayInMonth(2012, 1)
.Select(i => new DateTime(2012, 1, i)))
.ToList() // ForEach is not a Linq to Sql method (thanks #Markus Jarderot)
.ForEach(day => Console.Write(day));
You can do it with a simple loop:
DateTime first = new DateTime(2012, 1, 1);
for (DateTime current = first ; current.Month == first.Month ; current = current.AddDays(1)) {
}
It is fairly easy to generate an enumeration of days. Here is one way to do it
Enumerable.Range(1, DateTime.DaysInMonth(year, month)).Select(day =>
new DateTime(year, month, day))
Related
I have a date '2015-01-25'. How to get the remains date of Jan 2015. Is there any built in function to achieve this in c#
remains days ie, '2015-01-26','2015-01-27','2015-01-28','2015-01-29','2015-01-30','2015-01-31' etc..
Get Today
var today = DateTime.Now;
Get the first day of next month
var firstDayNextMonth = new DateTime(DateTime.Now.Year, DateTime.Now.AddMonths(1).Month, 1);
Create a list of the days between today and first day of next month (Enumerable.Range) Loop through the list and turn them into dates (Select) by adding each int to today
var dates = Enumerable.Range(0, firstDayNextMonth.Subtract(today).Days + 1)
.Select(d => today.AddDays(d))
.ToList();
If you want to find remaining days till next month, then you can add a day to the current DateTime in loop and check if the month of the new DateTime is same with yours. If the new DateTime met the condition, then add it to the list. If not, then break the loop.
You will use DateTime.AddDays() method which returns a new DateTime that adds the specified number of days to the value of this instance.
DateTime myDateTime = new DateTime(2015, 1, 25);
var remainedDateTimesToNextMonth = new List<DateTime>();
var nextDay = myDateTime;
while(true)
{
nextDay = nextDay.AddDays(1);
if (nextDay.Month == myDateTime.Month)
{
remainedDateTimesToNextMonth.Add(nextDay);
}
else break;
}
And int the result there would be six item inside remainedDateTimesToNextMonth list:
2015-01-26,2015-01-27,2015-01-28,2015-01-29,2015-01-30,2015-01-31
You can use DateTime.DaysInMonth(year, month) to get total days in months, and subtract the current day of month.
DateTime someDate = new DateTime(2015,1,25);
var remaining = DateTime.DaysInMonth(2015, 1) - someDate.Day;
Then you know the amount of remaining days for that given month, and can set up remaining dates in a list using an for loop.
List<DateTime> remainingDays = new List<DateTime>();
for (int i = 1; i <= remaining; i++)
{
remainingDays.Add(someDate.AddDays(i));
}
OK this code is a bit meta but it roughly explains how i have it now and what i want to achieve.
specialObject{
DateTime date;
int number;
}
var startDate = Lowest date in the list;
var endDate = Hightest date int the list;
List<SpecialObject> objs = (list from database where date > startDate and date < endDate)
//A list with alot of dates and numbers, most of the dates are the same. List contains roughly 1000 items, but can be more and less.
for(var date = startDate; date < endDate; date = date.AddDay(1){
listItem = objs.Where(x => x.Day = date).Sum(x => x.alotOfNUmbers);
}
Now since i don't care what day i calculate first, i thought i could do this.
Parallel.For(startDate, endDate, day => {
listItem = objs.Where(x => x.Day = date).Sum(x => x.alotOfNUmbers);
}
But how do i make it step dates ?
You can make a Range and iterate over it with Parallel.ForEach :
// not tested
var days = Enumerable
.Range(0, (endDate-startDate).Days) // check the rounding
.Select(i => startDate.AddDays(i));
Parallel.ForEach(days, day => ....)
Alternatively, you could use PLinq over the original source, probably faster. Roughly:
// not tested
var sums = objs.AsParallel().GroupBy(x => x.date).Select(g => g.Sum(i => i.number));
All the overloads of Parallel.For take two integer variables for start and end. I also don't see any version which would support something like a step so you can't just use the tick count of a DateTime as the loop variable.
But it should be easy to use a Parallel.ForEach instead, when you create an IEnumerable<DateTime> as the source sequence.
var source = Enumerable.Range(0, (endDate - startDate).Days)
.Select(t => startDate.AddDays(t));
Add +1 to the count parameter if the endDate is inclusive.
Ok after a few days search i figured if i placed all days in an array and "whiled" through it. It gives a pretty good result. With code easy to read
var start = new DateTime(2014, 09, 09);
var end = new DateTime(2014, 10, 01);
var listOfDays = new List<DateTime>();
int i = 0;
for (var day = start; day < end; day = day.AddDays(1))
{
listOfDays.Add(day);
}
Parallel.ForEach(listOfDays.ToArray(), currentDay =>
{
for (var d = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 0, 0, 0); d < new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 23, 59, 59); d = d.AddSeconds(5))
{
var str = "Loop: " + i + ", Date: " + d.ToString();
Console.WriteLine(str);
}
i++;
});
Console.Read();
I have a list of dates that are apart by a month in the sense that all dates are the "First Monday of the month". In some cases months are missing so I need to write a function to determine if all dates are consecutive
So for example if this was the list of dates, the function would return true as all items are the "First Friday of the month" and there are no gaps. This example below would return true.
var date = new DateTime(2013, 1, 4);
var date1 = new DateTime(2013, 2, 1);
var date2 = new DateTime(2013, 3, 1);
var date3 = new DateTime(2013, 4, 5);
var dateArray = new DateTime[]{date, date1, date2, date3};
bool isConsecutive = IsThisListConsecutive(dateArray);
where this example below would return false because, even though they are also all "First Friday of the month", its missing the March 2013 item.
var date = new DateTime(2013, 1, 4);
var date1 = new DateTime(2013, 2, 1);
var date3 = new DateTime(2013, 4, 5);
var dateArray = new DateTime[]{date, date1, date3};
bool isConsecutive = IsThisListConsecutive(dateArray);
so i am trying to figure out the right logic for the IsThisListConsecutive() method:
Here was my first try: (Note I already know upfront that all dates are same day of week and same week of month so the only thing i am looking for is a missing slot)
private bool IsThisListConsecutive(IEnumerable<DateTime> orderedSlots)
{
DateTime firstDate = orderedSlots.First();
int count = 0;
foreach (var slot in orderedSlots)
{
if (slot.Month != firstDate.AddMonths(count).Month)
{
return false;
}
count++;
}
return true;
}
This code above works exept if the list crosses over from one year to another. I wanted to get any advice on a better way to create this function and how that line could be rewritten to deal with dates that cross over years.
So to implement this we'll start with a simple helper method that takes a sequence and returns a sequence of pairs that make up each item with it's previous item.
public static IEnumerable<Tuple<T, T>> Pair<T>(this IEnumerable<T> source)
{
T previous;
using (var iterator = source.GetEnumerator())
{
if (iterator.MoveNext())
previous = iterator.Current;
else
yield break;
while(iterator.MoveNext())
{
yield return Tuple.Create(previous, iterator.Current);
previous = iterator.Current;
}
}
}
We'll also use this simple method to determine if two dates are in the same month:
public static bool AreSameMonth(DateTime first, DateTime second)
{
return first.Year == second.Year
&& first.Month == second.Month;
}
Using that, we can easily grab the month of each date and see if it's the month after the previous month. If it's true for all of the pairs, then we have consecutive months.
private static bool IsThisListConsecutive(IEnumerable<DateTime> orderedSlots)
{
return orderedSlots.Pair()
.All(pair => AreSameMonth(pair.Item1.AddMonths(1), pair.Item2));
}
Note: This is completely untested, and the date checks are probably pretty bad or somewhat redundant, but that’s the best I could come up with right now ^^
public bool AreSameWeekdayEveryMonth(IEnumerable<DateTime> dates)
{
var en = dates.GetEnumerator();
if (en.MoveNext())
{
DayOfWeek weekday = en.Current.DayOfWeek;
DateTime previous = en.Current;
while (en.MoveNext())
{
DateTime d = en.Current;
if (d.DayOfWeek != weekday || d.Day > 7)
return false;
if (d.Month != previous.Month && ((d - previous).Days == 28 || (d - previous).Days == 35))
return false;
previous = d;
}
}
return true;
}
I would recommend looking at the TimeSpan structure. Thanks to operator overload you can get a TimeSpan by substracting two dates and then receive a TimeSpan that expresses the difference between the two dates.
http://msdn.microsoft.com/en-us/library/system.timespan.aspx
okay, your code doesnt work when the years cross over becuase jan 1st may be a monday on one year and a tuesday on the next. If I was doing this, I would first check that
a) they are the same day of the week in each month (use DateTime.DayOfWeek)
b) they are the same week of the month in each month*
use extension method DayOfMonth (see link)
* Calculate week of month in .NET *
(you said you already know a & b to be true so lets go on to the third condition)
c) we have to determine if they are in consecutive months
//order the list of dates & place it into an array for ease of looping
DateTime[] orderedSlots = slots.OrderBy( t => t).ToArray<DateTime>();
//create a variable to hold the date from the previous month
DateTime temp = orderedSlots[0];
for(i= 1; index < orderedSlots.Length; index++)
{
if((orderedSlots[index].Month != temp.AddMonths(1).Month |
orderedSlots[index].Year != temp.AddMonths(1).Year)){
return false;
}
previousDate = orderedSlots[index];
}
return true;
if you need to check conditions a & b as well add change the if statement as follows
if( orderedSlots[index].Month != temp.AddMonths(1).Month |
orderedSlots[index].Year != temp.AddMonths(1).Year) |
orderedSlots[index].DayOfWeek != temp.DayOfWeek |
orderedSlots[index].GetWeekOfMonth != temp.AddMonths(1).GetWeekOfMonth){
return false;
}
remember that to use the get week of month extension method you have to include the code in
Calculate week of month in .NET
I'm sure there are typos as I did this in a text editor.
Well, here is my initial thought on how I would approach this problem.
First, is to define a function that will turn the dates into the ordinal values corresponding to the order in which they should appear.
int ToOrdinal(DateTime d, DateTime baseline) {
if (d.Day <= 7
&& d.DayInWeek == baseline.DayInWeek) {
// Since there is only one "First Friday" a month, and there are
// 12 months in year we can easily compose the ordinal.
// (As per default.kramer's comment, months normalized to [0,11].)
return d.Year * 12 + (d.Month - 1);
} else {
// Was not correct "kind" of day -
// Maybe baseline is Tuesday, but d represents Wednesday or
// maybe d wasn't in the first week ..
return 0;
}
}
var dates = ..;
var baseline = dates.FirstOrDefault();
var ordinals = dates.Select(d => ToOrdinal(d, baseline));
Then, for the dates provided, we end up with ordinal sequences like:
[24156 + 0, 24156 + 1, 24156 + 2, 24156 + 3]
And
[24156 + 0, 24156 + 1, /* !!!! */ 24156 + 3]
From here it is just a trivial matter of iterating the list and ensuring that the integers occur in sequence without gaps or stalls - that is, each item/integer is exactly one more than the previous.
I could be misinterpreting what you are trying to do, but I think this will work, assuming you don't have to handle ancient dates. See if there are any gaps in the dates converted to "total months"
int totalMonths = date.Year * 12 + (date.Month - 1);
I want to make a function that take month and year and return List<DateTime> filled with all dates in this month.
any help will be appreciated
Thanks in Advance
Here's a solution with LINQ:
public static List<DateTime> GetDates(int year, int month)
{
return Enumerable.Range(1, DateTime.DaysInMonth(year, month)) // Days: 1, 2 ... 31 etc.
.Select(day => new DateTime(year, month, day)) // Map each day to a date
.ToList(); // Load dates into a list
}
And one with a for-loop:
public static List<DateTime> GetDates(int year, int month)
{
var dates = new List<DateTime>();
// Loop from the first day of the month until we hit the next month, moving forward a day at a time
for (var date = new DateTime(year, month, 1); date.Month == month; date = date.AddDays(1))
{
dates.Add(date);
}
return dates;
}
You might want to consider returning a streaming sequence of dates instead of List<DateTime>, letting the caller decide whether to load the dates into a list or array / post-process them / partially iterate them etc. For the LINQ version, you can accomplish this by removing the call to ToList(). For the for-loop, you would want to implement an iterator. In both cases, the return-type would have to be changed to IEnumerable<DateTime>.
Sample for pre-Linq Framework versions, using February 1999.
int year = 1999;
int month = 2;
List<DateTime> list = new List<DateTime>();
DateTime date = new DateTime(year, month, 1);
do
{
list.Add(date);
date = date.AddDays(1);
while (date.Month == month);
I am sure there might be better ways to do this. But, you could use this:
public List<DateTime> getAllDates(int year, int month)
{
var ret = new List<DateTime>();
for (int i=1; i<=DateTime.DaysInMonth(year,month); i++) {
ret.Add(new DateTime(year, month, i));
}
return ret;
}
Here you go:
public List<DateTime> AllDatesInAMonth(int month, int year)
{
var firstOftargetMonth = new DateTime(year, month, 1);
var firstOfNextMonth = firstOftargetMonth.AddMonths(1);
var allDates = new List<DateTime>();
for (DateTime date = firstOftargetMonth; date < firstOfNextMonth; date = date.AddDays(1) )
{
allDates.Add(date);
}
return allDates;
}
Iterates through the dates from the first of the month you want through to the last date that's less than the first of the next month.
PS: If this is homework, please tag it with "homework"!
I can't think of an easy one or two liner that would get the previous months first day and last day.
I am LINQ-ifying a survey web app, and they squeezed a new requirement in.
The survey must include all of the service requests for the previous month. So if it is April 15th, I need all of Marches request ids.
var RequestIds = (from r in rdc.request
where r.dteCreated >= LastMonthsFirstDate &&
r.dteCreated <= LastMonthsLastDate
select r.intRequestId);
I just can't think of the dates easily without a switch. Unless I'm blind and overlooking an internal method of doing it.
var today = DateTime.Today;
var month = new DateTime(today.Year, today.Month, 1);
var first = month.AddMonths(-1);
var last = month.AddDays(-1);
In-line them if you really need one or two lines.
The way I've done this in the past is first get the first day of this month
dFirstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );
Then subtract a day to get end of last month
dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);
Then subtract a month to get first day of previous month
dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);
using Fluent DateTime https://github.com/FluentDateTime/FluentDateTime
var lastMonth = 1.Months().Ago().Date;
var firstDayOfMonth = lastMonth.FirstDayOfMonth();
var lastDayOfMonth = lastMonth.LastDayOfMonth();
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);
I use this simple one-liner:
public static DateTime GetLastDayOfPreviousMonth(this DateTime date)
{
return date.AddDays(-date.Day);
}
Be aware, that it retains the time.
An approach using extension methods:
class Program
{
static void Main(string[] args)
{
DateTime t = DateTime.Now;
DateTime p = t.PreviousMonthFirstDay();
Console.WriteLine( p.ToShortDateString() );
p = t.PreviousMonthLastDay();
Console.WriteLine( p.ToShortDateString() );
Console.ReadKey();
}
}
public static class Helpers
{
public static DateTime PreviousMonthFirstDay( this DateTime currentDate )
{
DateTime d = currentDate.PreviousMonthLastDay();
return new DateTime( d.Year, d.Month, 1 );
}
public static DateTime PreviousMonthLastDay( this DateTime currentDate )
{
return new DateTime( currentDate.Year, currentDate.Month, 1 ).AddDays( -1 );
}
}
See this link
http://www.codeplex.com/fluentdatetime
for some inspired DateTime extensions.
The canonical use case in e-commerce is credit card expiration dates, MM/yy. Subtract one second instead of one day. Otherwise the card will appear expired for the entire last day of the expiration month.
DateTime expiration = DateTime.Parse("07/2013");
DateTime endOfTheMonthExpiration = new DateTime(
expiration.Year, expiration.Month, 1).AddMonths(1).AddSeconds(-1);
If there's any chance that your datetimes aren't strict calendar dates, you should consider using enddate exclusion comparisons...
This will prevent you from missing any requests created during the date of Jan 31.
DateTime now = DateTime.Now;
DateTime thisMonth = new DateTime(now.Year, now.Month, 1);
DateTime lastMonth = thisMonth.AddMonths(-1);
var RequestIds = rdc.request
.Where(r => lastMonth <= r.dteCreated)
.Where(r => r.dteCreated < thisMonth)
.Select(r => r.intRequestId);
DateTime now = DateTime.Now;
int prevMonth = now.AddMonths(-1).Month;
int year = now.AddMonths(-1).Year;
int daysInPrevMonth = DateTime.DaysInMonth(year, prevMonth);
DateTime firstDayPrevMonth = new DateTime(year, prevMonth, 1);
DateTime lastDayPrevMonth = new DateTime(year, prevMonth, daysInPrevMonth);
Console.WriteLine("{0} {1}", firstDayPrevMonth.ToShortDateString(),
lastDayPrevMonth.ToShortDateString());
This is a take on Mike W's answer:
internal static DateTime GetPreviousMonth(bool returnLastDayOfMonth)
{
DateTime firstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );
DateTime lastDayOfLastMonth = firstDayOfThisMonth.AddDays (-1);
if (returnLastDayOfMonth) return lastDayOfLastMonth;
return firstDayOfThisMonth.AddMonths(-1);
}
You can call it like so:
dateTimePickerFrom.Value = GetPreviousMonth(false);
dateTimePickerTo.Value = GetPreviousMonth(true);
var lastMonth = DateTime.Today.AddMonths(-1);
dRet1 = new DateTime(lastMonth.Year, lastMonth.Month, 1);
dRet2 = new DateTime(lastMonth.Year, lastMonth.Month, DateTime.DaysInMonth(lastMonth.Year, lastMonth.Month));