I have this code, it failed because thisMonthSundays are empty:
public ActionResult TradeUKKPISearchesData() //show dropdownlist in the view
{
var now = DateTime.Now;
var lastMonth = now.AddMonths(-1);
var thisMonthSundays = GetDatesOfSundays(now.Year, now.Month).OrderByDescending(x => x.Date);
var lastMonthSundays = GetDatesOfSundays(lastMonth.Year, lastMonth.Month).OrderByDescending(x => x.Date); //problem here, must add some sort of check here?
var sundaysToTakeFromLastMonth = 4;
var sundays = thisMonthSundays.Concat(lastMonthSundays.Skip(Math.Max(0, lastMonthSundays.Count() - sundaysToTakeFromLastMonth)).Take(sundaysToTakeFromLastMonth));
var allSundaysInThisMonth = new SundaysInMonthViewModel
{
AllSundays = sundays.Select(x => new SelectListItem
{
Value = x.ToString("dd/MM/yyyy"),
Text = x.ToString("dd/MM/yyyy"),
})
};
var selectedSunday = new SundaysInMonthViewModel
{
SelectedSunday = thisMonthSundays.Where(x => x <= now).Last() //failed here
};
return View(allSundaysInThisMonth);
}
private IEnumerable<DateTime> GetDatesOfSundays(int year, int month)
{
var ci = CultureInfo.InvariantCulture;
for (int i=1; i <= ci.Calendar.GetDaysInMonth(year, month); i++)
{
var date = new DateTime(year, month, i);
if ((date.DayOfWeek == DayOfWeek.Sunday) && (date <= DateTime.Now))
{
yield return date; //skips all for this month
}
}
}
I need to fix this, please help with ideas?
thanks
As the Octobar month do not have SUnday so far, the variable SelectedSunday is empty....
You can use LastOrDefault() instead :
SelectedSunday = thisMonthSundays.Where(x => x <= now).LastOrDefault() ;
Note : The Default value for DateTime Type is DateTime.Min which is 1/1/0001 12:00:00 AM.
There are some mistakes in your code here.
Using var is not something you want to do everywhere.
You should never use arbitrary values in your functions. Instead of checking that the days are prior to today, you should add a limit parameter to your function and pass DateTime.Now
on the call.
Your function is already returning all the Sundays of a given month that are prior to today. Your Linq Request is just a replication of code and will return the whole collection every-time.
Since today is 10-01 and that we are Monday, there is no Sundays on October prior to today. This is why your collection is empty.
Related
I am facing a problem, logic written in my program is below
DataSet dslsip = mAE_Repo.FetchLastDayCustEmailsEquity_SIP_Content();
var ressip = (from r in dslsip.Tables[0].AsEnumerable() select r.Field<string>("emailid")).ToList();
var resdate = (from r in dslsip.Tables[0].AsEnumerable() select r.Field<DateTime>("a_confirmdatetime")).ToList();
//var datetime = DateTime.Now;
//List<string> date = new List<string>();
//List<DateTime> date = new List<DateTime>();
if (!ReferenceEquals(resdate,null) && resdate.Count>0)
{
for (int i = 0; i < resdate.Count()-1; i++)
{
if (resdate[i].Month == DateTime.Now.Month || resdate[i].Month < DateTime.Now.Month)
{
//Logic should write here
//var das = DateTime.Now.AddMonths(1).ToString("MM");
//var datet = resdate[i].AddMonths(1).ToString("MM");
}
}
}
In the above code 'resdate' variable I'm fetching the list of the dates
And the concept is I should add the month (current next month) Ex: {05-07-2021 00:00:00} I should add the (current month is 9 and next month is 10) so it should be {05-10-2021 00:00:00}
I'm not sure how to add the month only.
I'm new to coding.
Please help me in this.
Use AddMonths() function, example:
new DateTime(DateTime.Now.AddMonths(1).Year,
DateTime.Now.AddMonths(1).Month,
d.Day);
Output:
10/5/2021 12:00:00 AM
10/1/2021 12:00:00 AM
You need to change Month from date list. So, you can do it by using AddMonths() API. Used below Sample :
if (resdate[i].Month == DateTime.Now.Month || resdate[i].Month < DateTime.Now.Month)
{
//Logic should write here
var datet = new DateTime(resdate[i].Year, DateTime.Now.AddMonths(1).Month, resdate[i].Day, resdate[i].Hour, resdate[i].Minute, resdate[i].Second);
}
Here we modified only month data As you wanted.
I use nager.date to know if a day is a holiday day or a weekend day Saturday and Sunday).
I need to extract the date (starting from today or any other date) after 5 working days.
DateTime date1 = new DateTime(2019, 12, 23);
int i = 0;
while ( i < 5)
{
if (DateSystem.IsPublicHoliday(date1, CountryCode.IT) || DateSystem.IsWeekend(date1, CountryCode.IT))
{
date1 = date1.AddDays(1);
}
else
{
date1= date1.AddDays(1);
i++;
}
}
The problem of this code is that if the last else occurs, it add me 1 day but without doing any other check.
For example:
If the start date is 13/07/2020, the result will be at the end 18/07/2020 and as you can see is on Saturday.
How could I modify this code to achieve what I need?
The order is important. The AddDays should be called first, and after it is called we check if the new day matches our criteria.
Note: I have renamed the i variable so it is more clear.
DateTime date1 = new DateTime(2019, 12, 23);
int daysAdded = 0;
while (daysAdded < 5)
{
date1 = date1.AddDays(1);
if (!DateSystem.IsPublicHoliday(date1, CountryCode.IT) && !DateSystem.IsWeekend(date1, CountryCode.IT)) {
// We only consider laboral days
// laboral days: They are not holidays and are not weekends
daysAdded ++;
}
}
I always try to generalize my solutions, so here's one enabling LINQ:
public bool IsWorkingDay(DateTime dt)
=> !DateSystem.IsPublicHoliday(dt) && !DateSystem.IsWeekend(dt);
public DateTime NextWorkingDay(DateTime dt)
{
dt = dt.AddDays(1);
while (!IsWorkingDay(dt))
dt = dt.AddDays(1);
return dt;
}
public IEnumerable<DateTime> WorkingDaysFrom(DateTime dt)
{
if (!IsWorkingDay(dt))
dt = NextWorkingDay(dt); // includes initial dt, remove if unwanted
while (true)
{
yield return dt;
dt = NextWorkingDay(dt);
}
}
This will pump out working days from a given date until end of time, and then use LINQ to grab the number you want:
var next5 = WorkingDaysFrom(DateTime.Today).Take(5).ToList();
here's how to get all the working days in 2020:
var working2020 = WorkingDaysFrom(new DateTime(2020, 1, 1))
.TakeWhile(dt => dt.Year == 2020)
.ToList();
DateTime date1 = new DateTime(2019, 12, 23);
int i = 0;
while ( i < 5)
{
date1 = date1.AddDays(1);
if (!DateSystem.IsPublicHoliday(date1, CountryCode.IT) && !DateSystem.IsWeekend(date1, CountryCode.IT))
{
i++;
}
}
but I think that you need a DateTime[] to store all the five days
This is a better and a faster way to do this without using third party libraries.
DateTime nowDate = DateTime.Now;
DateTime expectedDate;
if (nowDate.DayOfWeek == DayOfWeek.Saturday)
{
expectedDate = nowDate.AddDays(6);
}
else if (nowDate.DayOfWeek == DayOfWeek.Sunday)
{
expectedDate = nowDate.AddDays(5);
}
else
{
expectedDate = nowDate.AddDays(7);
}
I thought about the problem, and based on the LINQ suggestion Lasse-v-Karlsen made, developed this code, which gives you most flexibility:
void Main()
{
// a list of public holidays
var holidays = new List<DateTime>() {new DateTime(2020,1,1),
new DateTime(2020,12,24), new DateTime(2020,12,25), new DateTime(2020,12,26)};
// a function checking if the date is a public holiday
Func<DateTime, bool> isHoliday = (dt) => holidays.Any(a=>a==dt);
// the start date
var dt = new DateTime(2020, 07, 13);
// end date, 5 working days later
var endDate = GetWorkingDay(dt, 5, isHoliday);
// print it
Console.WriteLine(endDate?.ToString("yyyy-mm-dd"));
}
public DateTime? GetWorkingDay(DateTime dt, int skipWorkingDays = 0,
Func<DateTime, bool> holidays=null)
{
if (holidays == null) holidays = (dt) => false;
IEnumerable<DateTime> NextWorkingDay(DateTime dt)
{
while (true)
{
var day = dt.DayOfWeek;
if (day != DayOfWeek.Saturday && day != DayOfWeek.Sunday
&& !holidays.Invoke(dt)) yield return dt;
dt = dt.AddDays(1);
}
}
if (skipWorkingDays<0) return null;
if (skipWorkingDays==0) return NextWorkingDay(dt).First();
var nextXDays = NextWorkingDay(dt).Take(skipWorkingDays).ToList();
var endDate = nextXDays.OrderByDescending(d => d).First();
return endDate;
}
Whether you have a list of public holidays like in this example, or a function coming from a library telling you if a date is a public holiday or not, just feel free to modify the Lambda function isHoliday. In your case, it would be defined as:
Func<DateTime, bool> isHoliday = (dt) => DateSystem.IsPublicHoliday(dt, CountryCode.IT);
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();
How to loop every month's first date.
public struct stat{
public DateTime date;
}
I have a List<stat> that have a date property. I want to get the lowest and newest one by sorting. the first element is older and last is newer one.
I can easily got the first and second by order by.
What I want is get 1st date of every month in the between of both first (oldest ) and newest.
string ret = "";
List<DateTime> dates = new List<DateTime>();
int breaker = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
stats = stats.OrderBy(x => x.Date).ToList();
DateTime old = stats.First().Date;
DateTime #new = stats.Last().Date;
int diffdays = #new.Subtract(old).Days;
DateTime loopd = DateTime.Now;
for (int i = 0; i < diffdays; i = i + breaker)
{
loopd = loopd.AddDays(-breaker);
dates.Add(loopd);
if (loopd < old)
Console.WriteLine("date" + old);
}
for (int j = 0; j < dates.Count; j++)
{
if (j == 0)
{
DateTime ld= dates[0];
stats.SelectMany(x => x.Date < #new && x.Date > dates[j]);
}
}
I want to get the lowest and newest one by sorting
I assume lowest means oldest.
stat oldest = stats.OrderBy(s => s.date).FirstOrDefault();
stat newest = stats.OrderByDescending(s => s.date).FirstOrDefault();
you could also use
stats.OrderBy(s => s.date).LastOrDefault();
to get the newest.
you could use something like this:
List<stat> statList = new List<stat>();
...
var selectedItem = statList
.OrderBy(item => item.date)
.Select(l => l.last());
or you could use OrderByDecending() instead
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));