I'm doing this test-app and what it has to do is go through a long list of dates from a text file and get the missing ones (excluding weekend days) and write the results to an output file. If the missing date is a single day the output should be ccyy/mm/dd , if it's more than one day it should be ccyy/mm/dd - ccyy/mm/dd , so this is what I've come up with and it doesn't seem to work as it should, I think I'm not doing the test right.
List<string> missigDateStrings = new List<string>();
for (int i = 0; i < dateList.Count; i++ )
{
DateTime firstDate = dateList[i];
DateTime secondDate = dateList[i + 1];
if (firstDate.DayOfWeek != DayOfWeek.Saturday &&
firstDate.DayOfWeek != DayOfWeek.Sunday)
{
if (secondDate.DayOfWeek != DayOfWeek.Saturday &&
secondDate.DayOfWeek != DayOfWeek.Sunday)
{
if (firstDate.AddDays(1) != secondDate)
{
string sFirstMissingDate = firstDate.ToShortDateString();
DateTime testDate = firstDate;
while (testDate != secondDate)
{
testDate.AddDays(1);
if (testDate == secondDate)
{
string sLastMissingDate = firstDate.AddDays(1).ToShortDateString();
string range = String.Format("{0}-{1}", sFirstMissingDate, sLastMissingDate);
missigDateStrings.Add(range);
}
}
}
}
}
}
}
Any help would be appreciated.
P.S. all the dates have been converted to DateTime
EXCELLENT ! THANKS ALL
If the gap is longer than 7 days you get weekend days also. I assume that is your problem. So you should add another check for Sat/Sun in
while (testDate != secondDate)
and break the loop on Friday, skip weekend and start loop on Monday again.
EDIT:
Below is always false in your case probably. That's why you don't get any output.
if (firstDate == secondDate)
Change
testDate.AddDays(1);
to
testDate = testDate.AddDays(1);
DateTime is an immutable value-type, AddDays() returns a new instance but does not (cannot) change the original value.
And just for fun, to answer the title-question,
var missing = Enumerable.Range(0, 10)
.Select(i => baseDate.AddDays(i))
.Except(datesFromFile);
Related
Good day everyone. I'm new to C# but I can't seem to understand how DateTime work.
All I wanted to do is to check If a (givenday) = today and time is 7pm I wanted to return true. Is this the right way to do it?
Take note ActionDate is a field which is inputed by the user.
DateTime dateA = Convert.ToDateTime(ActionDate);
int a = dateA.Year;
int b = dateA.Month;
int c = dateA.Day;
int d = timeA.Hour;
int e = timeA.Minute;
var newDate = new DateTime(a, b, c, d, e, 0);
DateTime end = Convert.ToDateTime(newDate);
DateTime start = Convert.ToDateTime(A);
TimeSpan span = end.Subtract(start);
Decimal minutes = Convert.ToDecimal(span.TotalMinutes);
if
{
return true;
} else
{
return false;
}
Thank you in advance.
The way to check if a give date is today and is at 7pm is to use DateTime.Now.
Note that 19 is 7pm and 7 is 7am, the Hour property uses 24 hour format.
bool IsCurrentDayAnd7(DateTime dt) => dt.Date == DateTime.Now.Date && dt.Hour == 19;
As #TimSchmelter commented you could use DateTime.Today:
bool IsCurrentDayAnd7(DateTime dt) => dt.Date == DateTime.Today && dt.Hour == 19;
You can use Date property to compare date with current date.
if (newDate.Date == DateTime.Now.Date && newDate.Hour == 19)
{
return true;
}
You have made your code a bit too complicated. First, convert that user input to date, and compate it with current date and time.
DateTime dateA = Convert.ToDateTime(ActionDate);
if (dateA.Date == DateTime.Today && dateA.Hour == 19)
{
//it is current date and hour is 7pm
}
Alternatively, check if user's imput is ok, like this:
DateTime dateA;
if (!DateTime.TryParse(ActionDate, out dateA))
{
//alert user that he's entered wrong date
}
EDIT:
as Tim Schmelter noted, code's a bit more readable using DateTime.Today instead of DateTime.Now.Date
In C#,
How we are check certain date with in week dates?
Eg: 6/02/2014
Current Weeks: 02/02/2014 - 08/02/2014
so this dates are with in above week....
Use this for check (last parameter is optional if you want always 1 week from fromDate, you don't need use last parameter):
public static bool DateInside(DateTime checkDate,
DateTime fromDate, DateTime? lastDate = null)
{
DateTime toDate = lastDate != null ? lastDate.Value : fromDate.AddDays(6d);
return checkDate >= fromDate && checkDate <= toDate;
}
To call use:
bool isDateInside = DateInside(new DateTime(2014, 02, 06),
new DateTime(2014, 02, 02)); // return true
And search first :) Answer is also here: How to check whether C# DateTime is within a range
If you want to check if the dates are inside the same week, then you can use this:
public static bool DateInsideOneWeek(DateTime checkDate, DateTime referenceDate)
{
// get first day of week from your actual culture info,
DayOfWeek firstWeekDay = System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek;
// or you can set exactly what you want: firstWeekDay = DayOfWeek.Monday;
// calculate first day of week from your reference date
DateTime startDateOfWeek = referenceDate;
while(startDateOfWeek.DayOfWeek != firstWeekDay)
{ startDateOfWeek = startDateOfWeek.AddDays(-1d); }
// fist day of week is find, then find last day of reference week
DateTime endDateOfWeek = startDateOfWeek.AddDays(6d);
// and check if checkDate is inside this period
return checkDate >= startDateOfWeek && checkDate <= endDateOfWeek;
}
Actual week in my culture info start with monday, February 3th 2014 (so for me is week between February 3th and February 9th). If I check any date with reference date (second parameter) as today (2014-Feb-06) I get this results:
For 2014-Feb-02 (Sunday before this week): false
For 2014-Feb-03 (Monday inside this week): true
For 2014-Feb-06 (Today inside this week): true
For 2014-Feb-09 (Sunday inside this week): true
For 2014-Feb-10 (Monday next week): false
You can call this method to check if one date is inside the same week as referentional like this:
DateInsideOneWeek(new DateTime(2014, 02, 02), new DateTime(2014, 02, 06));
You can find current week start and end dates with this code:
DateTime startDateOfWeek = DateTime.Now.Date; // start with actual date
while(startDateOfWeek.DayOfWeek != DayOfWeek.Monday) // set first day of week in your country
{ startDateOfWeek = startDateOfWeek.AddDays(-1d); } // after this while loop you get first day of actual week
DateTime endDateOfWeek = startDateOfWeek.AddDays(6d); // you just find last week day
Is this you wanted?
hmm
public bool isBetween(DateTime input, DateTime date1, DateTime date2)
{
if (input > date1 && input < date2)
return true;
else
return false;
}
?
input= your date
date1 & date2 = start and end of a week
How about:
bool inRange = (date >= lowerDate && date <= upperDate);
Here's another solution :)
public static class DateExtensions
{
private static void Swap<T>(ref T one, ref T two)
{
var temp = one;
one = two;
two = temp;
}
public static bool IsFromSameWeek(this DateTime first, DateTime second, DayOfWeek firstDayOfWeek = DayOfWeek.Monday)
{
// sort dates
if (first > second)
{
Swap(ref first, ref second);
}
var daysDiff = (second - first).TotalDays;
if (daysDiff >= 7)
{
return false;
}
const int TotalDaysInWeek = 7;
var adjustedDayOfWeekFirst = (int)first.DayOfWeek + (first.DayOfWeek < firstDayOfWeek ? TotalDaysInWeek : 0);
var adjustedDayOfWeekSecond = (int)second.DayOfWeek + (second.DayOfWeek < firstDayOfWeek ? TotalDaysInWeek : 0);
return adjustedDayOfWeekSecond >= adjustedDayOfWeekFirst;
}
}
Upd: it appears to have at least twice better performance than #Atiris solution :)
How would I get the number of weekday hours between two dates? (There's a lot of business days calculations, but doesn't seem to be much on weekday hours - not business/opening hours, just hours that aren't weekends).
This is my stab at it - is there a better way?
void Main()
{
// Works
DateTime start = new DateTime(2013,6,15,0,0,0); // Saturday
DateTime end = new DateTime(2013,6,17,10,0,0); // Monday
// Result = 10 (OK)
GetBusinessHours(start, end).Dump();
// Bugs
start = new DateTime(2013,6,14,0,0,0); // Friday
end = new DateTime(2013,6,15,0,0,0); // Saturday
// Result = 0 (Bug) - should be 24
GetBusinessHours(start, end).Dump();
}
public double GetBusinessHours(DateTime start, DateTime end)
{
double result = (end - start).TotalHours;
int weekendDays = Enumerable.Range(0, 1 + end.Subtract(start).Days).Select(offset => start.AddDays(offset)).Count(d => d.DayOfWeek == DayOfWeek.Sunday || d.DayOfWeek == DayOfWeek.Saturday);
double weekendDeltaHours = 0;
if (start.DayOfWeek == DayOfWeek.Saturday ||
start.DayOfWeek == DayOfWeek.Sunday)
{
weekendDays--;
weekendDeltaHours = start.Date.AddDays(1).Subtract(start).TotalHours;
}
else if (end.DayOfWeek == DayOfWeek.Saturday ||
end.DayOfWeek == DayOfWeek.Sunday)
{
weekendDeltaHours = (end - end.Date).TotalHours;
}
result = result - (weekendDays * 24) - weekendDeltaHours;
return result;
}
(Props to Ani for Enumerable.Range trick).
Not that this will be the most efficient method, it will work for what you require.
var end = DateTime.Now;
var start = end.AddDays(-100);
var weekend = new[] { DayOfWeek.Saturday, DayOfWeek.Sunday };
var count = Enumerable.Range(0, Convert.ToInt32(end.Subtract(start).TotalHours))
.Count(offset => !weekend.Contains(start.AddHours(offset).DayOfWeek));
It might be worth putting a check that the number of hours isn't too big for an int. However this would mean a date range of > 245,000 years!
So the user can select 2 different dates, a start date and an end date from 2 calendars, when they click add the dates between&including the dates selected will be added to the Database, each date as a separate record.
This works fine however I don't want weekends to be added to the Database.
I've updated the UI of datepicker http://www.kelvinluck.com/assets/jquery/datePicker/v2/demo/datePickerCustomCellRender.html
but if a user selects fri-mon for example fri,sat,sun and mon will be added to the Database.
I've tried to only run the code if datyofweek is not saturday or sunday
public ActionResult listHolidays(Holiday holiday, int? PersonId, string HolidayDate, string endDate)
{
DateTime startDates = Convert.ToDateTime(HolidayDate),
endDates = Convert.ToDateTime(endDate);
while (startDates <= endDates)
{
if (startDates.DayOfWeek != DayOfWeek.Saturday || startDates.DayOfWeek != DayOfWeek.Sunday)
{
Holiday holiday1 = new Holiday();
holiday1.PersonId = PersonId.Value;
holiday1.HolidayDate = startDates;
db.Holidays.AddObject(holiday1);
db.SaveChanges();
startDates = startDates.AddDays(1);
}
}
return RedirectToAction("Index");
}
any help?
Thanks
You need to use AND instead of OR:
if (startDates.DayOfWeek != DayOfWeek.Saturday && startDates.DayOfWeek != DayOfWeek.Sunday)
Your current condition will always be true. If startDates is DayOfWeek.Saturday, it is not DayOfWeek.Sunday and vice versa.
After that, you need to put the startDates = startDates.AddDays(1); outside the if.
Otherwise, you would have an endless loop, because as soon as startDates is DayOfWeek.Saturday, it will no longer be incremented.
Change
if (startDates.DayOfWeek != DayOfWeek.Saturday || startDates.DayOfWeek != DayOfWeek.Sunday)
To
if (startDates.DayOfWeek != DayOfWeek.Saturday && startDates.DayOfWeek != DayOfWeek.Sunday)
You'll then need to move this line
startDates = startDates.AddDays(1);
To outside of the if block (otherwise the startDates variable will never change if the date is a weekend date).
If statement is wrong and day increment in wrong place.
while (startDates <= endDates)
{
if (startDates.DayOfWeek != DayOfWeek.Saturday **&&** startDates.DayOfWeek != DayOfWeek.Sunday)
{
Holiday holiday1 = new Holiday();
holiday1.PersonId = PersonId.Value;
holiday1.HolidayDate = startDates;
db.Holidays.AddObject(holiday1);
db.SaveChanges();
}
**startDates = startDates.AddDays(1);**
}
Just as an alternative solution for you for calculating how many week days you have selected
List<DateTime> allDates = New List<DateTime>();
for (DateTime date = startingDate; date <= endingDate; date = date.AddDays(1))
allDates.Add(date);
var days = allDates.Where(x => x.IsWeekday()).Count();
Using the following DateTime extension.
public static class DateTimeExtensions
{
public static bool IsWeekday(this DateTime dt)
{
return dt.DayOfWeek != DayOfWeek.Sunday && dt.DayOfWeek != DayOfWeek.Saturday;
}
}
As per my comment, you can extend this to an IsWorkday if it is for a holiday system and encorporate some logic for checking if the day is a bank holiday.
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.