Timespan in an if else statement - c#

I have the following code, and I am planning to use it to check if the user has placed a correct number of days between two datetimepickers.
I've searched on google, and some posts say use var, some say parse, and still it wont work, the message box won't pop up upon checking.
I have already made it work by using a label as a container of the result and use an if else statement to check if the text is equal to 14,15 or 16. It works cause i only need to detect if its 14, 15 or 16, but what if i was given a situation where i need to compare large numbers, I wish I a better solution than what i have right now.
Can someone please tell me how to compare time spans in an if else statement properly? Thank you so much. have a nice day :)
DateTime dateFrom = from_dtPicker.Value;
DateTime dateTo = to_dtPicker.Value;
TimeSpan DayDifference = dateTo - dateFrom;
double NumberOfDays = DayDifference.TotalDays;
if ((NumberOfDays < 14) && (NumberOfDays > 16))
{
//message box
}
Here's what i mean with my weird solution though,
DateTime dateFrom = pp_from_dtPicker.Value;
DateTime dateTo = pp_to_dtPicker.Value;
TimeSpan DayDifference = dateTo - dateFrom;
numofdaysLBL.Text = DayDifference.TotalDays.ToString();
if ((numofdaysLBL.Text != "14") && (numofdaysLBL.Text != "15") && (numofdaysLBL.Text != "16"))
{
//msgbox
}

It seems to me, that your comparison is the problem here
if ((NumberOfDays < 14) && (NumberOfDays > 16))
NumberOfDays can never be less than 14 AND more than 16 at the same time. Instead invert the comparison:
if ((NumberOfDays >= 14) && (NumberOfDays <= 16))
EDIT: Maybe I misunderstood what you are asking (as pointed out in the comments). If you want a more generic solution for comparing dates, you can simply wrap your code into a function
bool AreDatesClose(DateTime d1, DateTime d2, double minDaysApart, double maxDaysApart)
{
var timespan = d1 - d2;
return timespan.TotalDays >= minDaysApart && timespan.TotalDays <= maxDaysApart;
}

You can write a function which will give you that NumberOfDays is in between given range or not
public bool IsGivenDateInRange(double numberOfDays, double startDate, double endDate)
{
return numberOfDays >= startDate && numberOfDays <= endDate;
}
Now use this function in if condition
if(IsGivenDateInRange(NumberOfDays, 14, 16)) //Instead of 14 and 16 you can use any number
{
//Your logic
}
As per new edit in your question if you want to show message box when date does not come in these range, then you can use same function but with negation
if(!IsGivenDateInRange(NumberOfDays, 14, 16)) //Instead of 14 and 16 you can use any number
{
//MessageBox.Show();
//Your logic
}

Related

Get DateTime of the next nth day of the month

If given a date and a variable n, how can I calculate the DateTime for which the day of the month will be the nth Date?
For example, Today is the 17th of June.
I would like a function that when provided 15 would return the DateTime for July 15.
A few more examples:
Today is Feb. 26: Function would return March 30 when provided 30.
Today is Dec. 28. Function would return Jan 4 when provided 4.
Today is Feb. 28. Function would return March 29 when provided 29, unless it was a leap year, in which case it would return Feb 29.
Why not just do?
private DateTime GetNextDate(DateTime dt, int DesiredDay)
{
if (DesiredDay >= 1 && DesiredDay <= 31)
{
do
{
dt = dt.AddDays(1);
} while (dt.Day != DesiredDay);
return dt.Date;
}
else
{
throw new ArgumentOutOfRangeException();
}
}
After many, many edits, corrections and re-writes, here is my final answer:
The method that follows returns a a DateTime representing the next time the day of number day comes up in the calendar. It does so using an iterative approach, and is written in the form of an extension method for DateTime objects, and thus isn't bound to today's date but will work with any date.
The code executes the following steps to get the desired result:
Ensure that the day number provided is valid (greater than zero and smaller than 32).
Enter into a while loop that keeps going forever (until we break).
Check if cDate's month works (the day must not have passed, and the month must have enough days in it).
If so, return.
If not, increase the month by one, set the day to one, set includeToday to true so that the first day of the new month is included, and execute the loop again.
The code:
static DateTime GetNextDate3(this DateTime cDate, int day, bool includeToday = false)
{
// Make sure provided day is valid
if (day > 0 && day <= 31)
{
while (true)
{
// See if day has passed in current month or is not contained in it at all
if ((includeToday && day > cDate.Day || (includeToday && day >= cDate.Day)) && day <= DateTime.DaysInMonth(cDate.Year, cDate.Month))
{
// If so, break and return
break;
}
// Advance month by one and set day to one
// FIXED BUG HERE (note the order of the two calls)
cDate = cDate.AddDays(1 - cDate.Day).AddMonths(1);
// Set includeToday to true so that the first of every month is taken into account
includeToday = true;
}
// Return if the cDate's month contains day and it hasn't passed
return new DateTime(cDate.Year, cDate.Month, day);
}
// Day provided wasn't a valid one
throw new ArgumentOutOfRangeException("day", "Day isn't valid");
}
The spec is a little bit unclear about to do when today is the dayOfMonth. I assumed it was it to return the same. Otherwise it would just be to change to <= today.Day
public DateTime FindNextDate(int dayOfMonth, DateTime today)
{
var nextMonth = new DateTime(today.Year, today.Month, 1).AddMonths(1);
if(dayOfMonth < today.Day){
nextMonth = nextMonth.AddMonths(1);
}
while(nextMonth.AddDays(-1).Day < dayOfMonth){
nextMonth = nextMonth.AddMonths(1);
}
var month = nextMonth.AddMonths(-1);
return new DateTime(month.Year, month.Month, dayOfMonth);
}
Stumbled upon this thread today while trying to figure out this same problem.
From my testing, the following seems to work well and the loop only needs two goes (I think? Maybe 3 max(?)) to get to the answer:
public static DateTime GetNearestSpecificDay(DateTime start, int dayNum)
{
if (dayNum >= 1 && dayNum <= 31)
{
DateTime result = start;
while (result.Day != dayNum)
result = dayNum > result.Day ? result.AddDays(dayNum - result.Day) : new DateTime(result.Month == 12 ? result.Year + 1 : result.Year, (result.Month % 12) + 1, 1);
return result;
}
else
return DateTime.Today;
}
Edit: As requested, here's a less compact version that walks through the logic step by step. I've also updated the original code to account for a required year change when we reach December.
public static DateTime GetNearestSpecificDay(DateTime start, int dayNum)
{
// Check if target day is valid in the Gregorian calendar
if (dayNum >= 1 && dayNum <= 31)
{
// Declare a variable which will hold our result & temporary results
DateTime result = start;
// While the current result's day is not the desired day
while (result.Day != dayNum)
{
// If the desired day is greater than the current day
if (dayNum > result.Day)
{
// Add the difference to try and skip to the target day (if we can, if the current month does not have enough days, we will be pushed into the next month and repeat)
result = result.AddDays(dayNum - result.Day);
}
// Else, get the first day of the next month, then try the first step again (which should get us where we want to be)
else
{
// If the desired day is less than the current result day, it means our result day must be in the next month (it obviously can't be in the current)
// Get the next month by adding 1 to the current month mod 12 (so when we hit december, we go to january instead of trying to use a not real 13th month)
// If result.Month is November, 11%12 = 11; 11 + 1 = 12, which rolls us into December
// If result.Month is December, 12%12 = 0; 0 + 1 = 1, which rolls us into January
var month = (result.Month % 12) + 1;
// Get current/next year.
// Since we are adding 1 to the current month, we can assume if the previous month was 12 that we must be entering into January of next year
// Another way to do this would be to check if the new month is 1. It accomplishes the same thing but I chose 12 since it doesn't require an extra variable in the original code.
// Below can be translated as "If last result month is 12, use current year + 1, else, use current year"
var year = result.Month == 12 ? result.Year + 1 : result.Year;
// Set result to the start of the next month in the current/next year
result = new DateTime(year, month, 1);
}
}
// Return result
return result;
}
else
// If our desired day is invalid, just return Today. This can be an exception or something as well, just using Today fit my use case better.
return DateTime.Today;
}
Fun little puzzle. I generated 100 DateTimes which represent the starting day of each month, then checked each month to see if it had the date we want. It's lazy so we stop when we find a good one.
public DateTime FindNextDate(int dayOfMonth, DateTime today)
{
DateTime yesterday = today.AddDays(-1);
DateTime currentMonthStart = new DateTime(today.Year, today.Month, 1);
var query = Enumerable.Range(0, 100)
.Select(i => currentMonthStart.AddMonths(i))
.Select(monthStart => MakeDateOrDefault(
monthStart.Year, monthStart.Month, dayOfMonth,
yesterday)
.Where(date => today <= date)
.Take(1);
List<DateTime> results = query.ToList();
if (!results.Any())
{
throw new ArgumentOutOfRangeException(nameof(dayOfMonth))
}
return results.Single();
}
public DateTime MakeDateOrDefault(
int year, int month, int dayOfMonth,
DateTime defaultDate)
{
try
{
return new DateTime(year, month, dayOfMonth);
}
catch
{
return defaultDate;
}
}

Daterange with startDate and endDate not working if both date same

I get the data returned of the selected date range which is between the range or isnt. but not if the startDate and endDate is the same. Like example: from 14.10.2017 - 14.10.2017. It returns me then no data (but it should because 5 database records are affected)
foreach (Content content in db.Contents)
{
if (content.ShippedDate < startDate || content.ShippedDate > endDate)
}
Anyone has a solution?
You should update the condition to include the same date.
1.1.2016 < 1.1.2016 //FALSE
1.1.2016 <= 1.1.2016 //TRUE
Adjusting conditions:
content.ShippedDate <= startDate
content.ShippedDate >= endDate
Code:
foreach (Content content in db.Contents)
{
if (content.ShippedDate <= startDate || content.ShippedDate >= endDate)
//the code here
}
use <= (smaller than or equal) and >= (greater than or equal) instead of < and >, this will match values that are equal as well rather than just the ones that are smaller or greater than given value.
Also please refer to this page to learn more about c# operators as this is a very basic questions
https://msdn.microsoft.com/en-us/library/6a71f45d.aspx

How to check if a day is a certain date in asp.net c#.net

I would like to check, if a rendered day in a webcalendar-element is X-mas Eve or the first of January or another date of a year and if so, colour that date differently.
So if the day rendered is the third Monday in May, colour it differently. If it is X-mas eve, colour it differently and so forth.
All ive found so far is how to extract the day to a specific date. But I would like to do kinda the opposite. Has anyone done that and can offer some tips?
It's not really clear what you mean by "do kinda the opposite" but:
static IsThirdMondayInMay(DateTime date)
{
// The first X in a month is always in the range [1, 8)
// The second X in a month is always in the range [8, 15)
// The third X in a month is always in the range [15, 22)
return date.Month == 5 && date.DayOfWeek == DayOfWeek.Monday &&
date.Day >= 15 && date.Day < 22;
}
static IsChristmasEve(DateTime date)
{
return date.Month == 12 && date.Day == 24;
}
Or more generally for the last:
static MonthDayMatches(DateTime date, int month, int day)
{
return date.Month == month && date.Day == day;
}
then:
bool christmasEve = MonthDayMatches(date, 12, 24);
I assume you are using the ASP.NET Calendar control. Then use the DayRender event. This has an argument Day with a property Date which is the DateTime. Now you can use this date to decide whether it is a special day or not.
void DayRender(Object source, DayRenderEventArgs e)
{
DateTime date = e.Day.Date; // here it is
if(IsSpecialDay(date)) // your method to determine if a given date is a "special"-date
e.Cell.BackColor = System.Drawing.Color.Gold; // or use the Style property to use CSS
}

C# DateTime falls within the last 24 hours

I have a DateTime object that I'd like to check and see if it falls within the last 24 hours.
I did something like this but its wrong:
myDateTime > DateTime.Now.AddHours(-24) && myDateTime < DateTime.Now
where did I go wrong?
There is nothing wrong with the code that you posted, so whatever you did wrong is somewhere else in the code.
I only see two minor flaws in the code, but they only affect corner cases:
You should avoid getting the DateTime.Now property repeatedly in the code. Its value changes, so you may get inconsistent results in some cases when the values changes from one use to the next.
To get a time interval you would usually pair one inclusive and one exclusive operator, like > and <=, or >= and <. That way you can check for intervals next to each other, like 0 - 24 hours and 24 - 28 hours, without getting a gap or an overlap.
DateTime now = DateTime.Now;
if (myDateTime > now.AddHours(-24) && myDateTime <= now)
Only get DateTime.Now once within the function - otherwise the value might change.
Use <=, not <. if you check a microsecond after the time has been set, it will still be equal to DateTime.Now. I actually ran into this in production code where imports wouldn't show up in a different query that checked < because the import was too fast!
Use this code:
DateTime now = DateTime.Now;
DateTime yesterday = now.AddDays(-1);
if (myDateTime > yesterday && myDateTime <= now) {
...
}
Learning from both the above answers and also to improve the readability of the code we can use a method like this.
using System;
public class Program
{
public static void Main()
{
DateTime myDateTime = DateTime.Parse("2021-08-25T20:20:19.5540211");
DateTime now = DateTime.Now;
DateTime yesterday = now.AddHours(-24);
if (IsBewteenTwoDates(myDateTime, yesterday, now))
{
Console.WriteLine("this date ({0}) is between {1} & {2}", myDateTime, yesterday, now);
}
else
{
Console.WriteLine("this date ({0}) is not between {1} & {2}", myDateTime, yesterday, now);
}
}
// Checks if the DateTime object dt is between start and end DateTime.
public static bool IsBewteenTwoDates(DateTime dt, DateTime start, DateTime end)
{
return dt >= start && dt <= end;
}
}
Check the fiddle here.

DateTime casting/magic

Is there a nice concise way to write this logic in C#?
if ((DateTime.Now >= "8:00 AM") && (DateTime.Now < 5:00 PM))
{// do something}
I am making a demo app where I want to make something happen in the work day, but I don't want this code to stand out much (a lot of casting = bad). (Because I want my demo stuff to be easier to see.
Well, you could do:
DateTime now = DateTime.Now;
if (now.Hour < 8 || now.Hour >= 17)
Note that I generally prefer to only use the DateTime.Now property once, copying the result into the local variable as above - that way you don't get odd possibilities due to the time changing between calls. Not a problem here, but it could be in other cases.
Another possibility is to use DateTime.TimeOfDay if you want to handle things that way. I think the above is about as simple as it gets though.
EDIT: Steven pointed out that I changed the && in your original logic to || - your original logic can never work, as it can never be before 8am and after 5pm. The above works for "if it's not in the working day" - if you want "if it is in the working day" you just need:
DateTime now = DateTime.Now;
if (now.Hour >= 8 && now.Hour < 17)
I think what you want to do here is something like this:
var now = DateTime.Now;
if (now.Hour >= 8 && now.Hour < 17)
If you wanted to make it "pretty" you could also use an extension method:
public static class DateTimeHelper
{
public static DateTime Time(this string time)
{
DateTime theTime = DateTime.Parse(time);
return theTime;
}
}
...
if (DateTime.Now < "8:00 AM".Time() && DateTime.Now > "5:00 PM".Time())
{
// do something
}
If you can format a string in the right format for the current date and start / end times you can use something like this.
DateTime now = DateTime.Now;
DateTime start = Convert.ToDateTime(now.Date.ToShortDateString() + " 8:00:00 AM");
DateTime end = Convert.ToDateTime(now.Date.ToShortDateString() + " 5:00:00 PM");
if (now >= start && now < end)
{
}
I still think it's cleaner to use the hour method posted by others, but this is a method that provides an answer similar to how you asked your question.

Categories

Resources