C# DateTime falls within the last 24 hours - c#

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.

Related

Decrement date month transition

I have a function to decrement a date by one day each time is called.
private IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
for (var day = thru.Date; day.Date >= from.Date; day = day.Subtract(TimeSpan.FromDays(1)))//day.AddDays(-1))
{
yield return day;
}
}
Seems to work fine until i arrive to the previous month. If someone have a solution ?
I would be using something like this
private IEnumerable<DateTime> EachDay(DateTime from, DateTime thru)
{
var days=(thru.Date - from.Date).Days;
if (days <= 0) yield return DateTime.MinValue;
else for (var day = days; day >= 0; day-=1)
yield return from.Date.AddDays(day);
}
test
var thru =new DateTime(day: 01,month:12, year:2021);
var from= thru.AddDays(-10);
EachDay(from,thru).Dump();
result
2021-12-01
2021-11-30
2021-11-29
2021-11-28
2021-11-27
2021-11-26
2021-11-25
2021-11-24
2021-11-23
2021-11-22
2021-11-21
My other answer notwithstanding, you said in a comment on Serge's answer:
when i give 01/12/2021 the response is 01/00/2021
I just wanted to point out that you may get this if you have a date of midnight on 01/12/2021 and you accidentally use a date format of dd/mm/yyyy when printing it out
mm is minutes, not months. MM is months.. If you're stringing your date using mm the 00 you're seeing is the minute from 00:00:00 time, not the month
All in your entire code might be fine (it seems fine to me) and you're being misled by a typo in a ToString
Finally got it. I store the value in a database and a piece of code induce an implicit conversion from native date format to french date format.
I force to use the native date format into all code and all is now fine.
Thanks for your response
To some extent you're reinventing a wheel here. You can use Enumerable.Range to do your dates:
var f = // the date from eg DateTime.Now;
var t = // the date to eg DateTime.Now.AddDays(-45);
//this line of code generates the dates
var d = Enumerable.Range(0, 1 + (int)((f-t).TotalDays)).Select(x => f.AddDays(-x));
The dates in d have no problem crossing a month boundary

Comparing times without date?

I am having trouble comparing times.
From what I have researched it most likely is due to the time not having a date.
My code,
This gets a dateTime value from the database.
var getDateTime = sql.Staff_Time_TBLs.Where(p => p.Staff_No ==
SelectedEmployee.Key && p.Date_Data == day).Select(p => p.Time_Data_1).ToList();
DateTime dateTimeGet = Convert.ToDateTime(getDateTime);
dateTimeGet returns a value like this "2012/12/12 15:03:00.000"
I then declare variables to hold the time.
TimeSpan startCompare = TimeSpan.Parse("15:00");
TimeSpan endCompare = TimeSpan.Parse("21:00");
Then comparing the values Compare DateTime
if ((endCompare > dateTimeGet) && (startCompare < dateTimeGet))
{
//match found
}
I am getting a compile error,
operands cannot be given to to type timespan and datetime
How do I compare times in this situation?
Just edit your code like this:
if ((endCompare > dateTimeGet.TimeOfDay) && (startCompare < dateTimeGet.TimeOfDay))
{
//match found
}
You could create DateTime values instead of TimeSpan to compare the value, using the Date of your db time:
DateTime startCompare = dateTimeGet.Date.AddHours(15);
DateTime endCompare = dateTimeGet.Date.AddHours(21);
if ((endCompare > dateTimeGet) && (startCompare < dateTimeGet))
{
// match found
}
In the example you showed, actually would be enough to compare the Hour part of dateTimeGet:
if (dateTimeGet.Hour >= 15 && dateTimeGet.Hour <= 21)
// match found
Actually you are comparing time with date in endCompare > dateTimeGet so you are getting the error
operands cannot be given to to type timespan and datetime
To compare time-span you need to extract the time from date in dateTimeGet by simply using TimeOfDay.
if ((endCompare > dateTimeGet.TimeOfDay) && (startCompare < dateTimeGet.TimeOfDay))
{
//match found
}
This will convert the date into time. For more details about TimeOfDayclick here Hope this works fine for you.
The issue is that, as you rightly say, you are comparing dates to times
A time-span is a measurement of time measured in Hours, where as a date-time is a measurement of time measured in days
so 2012/12/12 15:03:00.000 is approximately 735248.625 days or 17645967 hours
which you are then comparing to a timespan of 15 hours
so you need to either add 735248 days to your time span or drop 735248 days form your Date
both can be easily done
If you call the time TimeOfDay property on the date it will ignore the days and just return 0.625 days as 15 hours
Which means your code would look like this
if ((endCompare > dateTimeGet.TimeOfDay ) && (startCompare < dateTimeGet.TimeOfDay))
OR
If you add the time span to the at midnight date it will create the correct date time for comparation
Which means your code would look like this
if ((dateTimeGet.Date + endCompare > dateTimeGet ) && (dateTimeGet.Date + startCompare < dateTimeGet.TimeOfDay))

Disabling weekend and national Holidays in ajax calendar extender control

I have been trying to use an ajax CalenderExtender for my application.
I have many small operations in my app like adding duration to start date of a task to find the finish date, change duration of a task if its end date is changed (depending on its start date),etc.
But while I do all these operations I want to skip all the holidays and saturday , sundays from the calculations for eg. a task starting on 01/23/2014 with a duration of 5 days should finish on 01/29/2014 (adding 2 days for sat n sun in duration) instead of 01/27/2014. Same should be performed on other operations as well.
Is there a way to do this?
For Sundays and Saturdays, it's easy. Just check the DateTime.DayOfWeek property of your dates.
If you have an operation that will start on date start and will end on date end, you can see what dates are Saturdays or Sundays like this:
List<DateTime> satsAndSundays;
for (DateTime temp = start; temp <= end; temp.AddDays(1))
{
if (temp.DayOfWeek == DayOfWeek.Sunday ||
temp.DayOfWeek == DayOfWeek.Saturday)
{
satsAndSundays.add(temp);
}
}
And since you can know how many days there are between start and end by doing something like:
TimeSpan span = end - start;
int totalDays = (int)span.TotalDays;
// TotalDays is actually a double, I'm just discarding the non integer part.
You may fid out how many work days you have there by doing totalDays - satsAndSundays.Count.
Edit: I just read the question again. If you want a task to start on a given date, and take x work days, you can do it like this:
DateTime end = start;
for (int i = x; i >= 0;) // the third parameter of the for is empty on purpose
{
end = end.AddDays(1);
if (end.DayOfWeek != DayOfWeek.Saturday &&
end.DayOfWeek != DayOfWeek.Sunday)
{
i--;
}
}
Afther the loop, end will be x workdays after start (provided there are no holidays in between).
For holidays, though, there is no alghoritm for that in the framework. You need to fetch them from some source (a file, a database, a web service etc.). Or you could write your own program to figure them out - most holidays that are not on a fixed date do follow formulas when it comes to when they happen. Do take into account, however, that holidays may vary by culture and region. If your application is to be used throughout a country, for example, it may be quite the effort to implement city-wide holidays. Depending on your needs, it might even be better to either let the users input which days are holidays, or making your own database your app can access and use.
Try this one..
private string GetDatesOfSundays(DateTime DatMonth)
{
string sReturn = "";
int iDayOffset = DatMonth.Day - 1;
DatMonth = DatMonth.AddDays(System.Convert.ToDouble(-DatMonth.Day + 1));
DateTime DatMonth2 = DatMonth.AddMonths(1).AddDays(System.Convert.ToDouble(-1));
while (DatMonth < DatMonth2)
{
if (DatMonth.DayOfWeek == System.DayOfWeek.Sunday)
{
if (sReturn.Length > 0) sReturn += ",";
sReturn += DatMonth.ToShortDateString();
}
DatMonth = DatMonth.AddDays(1.0);
}
return sReturn;
}

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.

DateTime of next 3am occurrence

I'm sure this is very easy, but I've got a sudden mental block.
I'm trying to get a DateTime object for the next occurence of 3am. For example, if DateTime.Now is 16/july/2009 : 12:04pm - the next occurance of 3am would be 17/july/2009 : 03:00
However, if DateTime.Now was 17/july/2009 : 01:00 then the next occurence would still be 17/july/2009 : 03:00 (not the day after).
Does that make sense?
One option:
DateTime now = DateTime.Now;
DateTime today3am = now.Date.AddHours(3);
DateTime next3am = now <= today3am ? today3am : today3am.AddDays(1);
Another:
DateTime now = DateTime.Now;
DateTime today = now.Date;
DateTime next3am = today.AddHours(3).AddDays(now.Hour >= 3 ? 1 : 0)
Lots of ways of skinning that particular cat :)
This is all in local time of course, which means you don't need to worry about time zones. Life becomes trickier if you want to get time zones involved...
Note that it's a good idea to take DateTime.Now once to avoid problems if the date rolls over while you're calculating...
DateTime now = DateTime.Now;
DateTime threeAM = now.Date.AddHours(3);
if (threeAM < now)
threeAM = threeAM.AddDays(1);
//just add 24 - 3 = 21 hours and get Today (start of day) and Add 3 hour
DateTime now = DateTime.Now.AddHours(21).Today.AddHours(3);
An alternative (using a function):
DateTime NextAt(TimeSpan time)
{
DateTime now = DateTime.Now;
DateTime result = now.Date + time;
return (now <= result) ? result : result.AddDays(1);
}
call it like:
DateTime next3am = NextAt(new TimeSpan(3,0,0));
You can do it without an if statement (or conditional operator):
// get the current time
DateTime now = DateTime.Now;
// get a 3:00 AM point in time in the future
DateTime next = now.Date.AddHours(24 + 3);
// subtract the number of whole extra days
next = next.AddDays((now - next).Days);
I always explain that you should get the point in time (DateTime.Now) only once in a calculation like this, as it's a changing value, so do I have to repeat it? Well, I just did. ;)
I think this One:
DateTime.Now.Date.AddHours(3).AddMinutes(0).AddSeconds(0).AddDays(1);

Categories

Resources