3

I need to run a job/scheduler, which should only update records in database it is falling under the specified time range. In my case, the time range is from 3.30 AM to next day 1.30AM. So, with in this time frame the job needs to update the records. In order to get this time interval, I using TimeOfDay() function, but my logic is getting failed, bcoz if the currenttime is say 6.00 Am, then "currentTime <= todaysJob.ENDTIME.Value.TimeOfDay" is returning false. I am using the below code to check

     var currentTime = DateTime.Now.TimeOfDay;
     if (currentTime > todaysJob.STARTTIME.Value.TimeOfDay && 
          currentTime <= todaysJob.ENDTIME.Value.TimeOfDay)
            {
                // Do logic
            }
Developer
  • 759
  • 2
  • 9
  • 24
  • what did you stored in currentTime? – VIRA Aug 31 '12 at 04:41
  • 1
    You've got to mark the date of the task, because the time component reflects to 24 hours a day and it doesn't know anything about the date...so your morning of tomorrow equals today's morning and your condition is always false – horgh Aug 31 '12 at 04:47
  • You could make your life easier by [introducing a Range object](http://stackoverflow.com/a/1845523/540352). – Laoujin Aug 31 '12 at 08:40

4 Answers4

1
        bool endTomorrow = true;

        DateTime taskDate = new DateTime(2012, 08, 31);

        TimeSpan Start = new TimeSpan(03, 30, 00);
        TimeSpan End = new TimeSpan(01, 30, 00);

        DateTime currentTime = DateTime.Now;

        bool flag = false;

        if (currentTime.TimeOfDay >= Start)
        {
            if (endTomorrow)
            {
                flag = currentTime.Date <= taskDate || (currentTime.Date == taskDate.AddDays(1) && currentTime.TimeOfDay < End);
            }
            else
            {
                flag = currentTime.TimeOfDay < End;
            }
        }

        if (flag)
        {
            //do the task
        }

EDIT

So I added:

  1. a boolean flag, determining whether the task should end the next day
  2. a datetime variable (taskDate) saying the date of the task

Start and End are equal to todaysJob.STARTTIME and todaysJob.ENDTIME, so you take them from DB as they are.

EDIT

If you could have your job like this:

public class Job
{
    public TimeSpan STARTTIME;
    public TimeSpan ENDTIME;
    public DayOfWeek taskDayOfWeek;
    public bool IsEndingTommorow;

    public bool IsTomorrow(DayOfWeek d)
    {
        if (d == DayOfWeek.Sunday)
            return taskDayOfWeek == DayOfWeek.Saturday;
        else
            return d <= taskDayOfWeek;
    }
}

then you could

        DateTime currentTime = DateTime.Now;

        bool flag = false;

        if (currentTime.TimeOfDay >= todaysJob.STARTTIME)
        {
            if (todaysJob.IsEndingTommorow)
            {
                flag = currentTime.DayOfWeek == todaysJob.taskDayOfWeek || (todaysJob.IsTomorrow(currentTime.DayOfWeek) && currentTime.TimeOfDay < todaysJob.ENDTIME);
            }
            else
            {
                flag = currentTime.TimeOfDay < todaysJob.ENDTIME;
            }
        }

        if (flag)
        {
            //do the task
        }

EDIT

I've edited my code another time: added a method to avoid problems with the DayOfWeek enum

horgh
  • 17,918
  • 22
  • 68
  • 123
  • Start and end time is coming from database, so I can't get it like the way you suggested. Moreover, there r many schedules which needs to be run, and all have different Start and End time. – Developer Aug 31 '12 at 05:00
  • @Nick please, have a look at it – horgh Aug 31 '12 at 05:12
  • I don't have TaskDate with me, but TaskDate = DateTime.Now; is fine? – Developer Aug 31 '12 at 05:19
  • @Nick No, it isn't fine, when tomorrow comes DateTime.Now will be = taskdate + 1, and you'll get incorrect results – horgh Aug 31 '12 at 05:23
  • @Nick You should have the task date separetely, or consider using different logic – horgh Aug 31 '12 at 05:23
  • @Nick If your "scheduler day" (let's call it so) differs from usual day, these extra fields are necessary. – horgh Aug 31 '12 at 05:26
  • In my database, I have columns to check if the job needs to be run on Monday/Tuesday/Wed.. like wise, and based on that i fetch all the jobs which needs to be run. – Developer Aug 31 '12 at 05:34
  • @Nick I've edited my post, now it's using day of a week to check tomorrow and today, try it – horgh Aug 31 '12 at 05:47
  • Thanks for helping me out of this issue. – Developer Aug 31 '12 at 07:05
  • @Nick You're welcome! Consider using upvotes or mark as the answer those posts that really helped you though – horgh Aug 31 '12 at 07:09
1

You can use the Time Period Library for .NET, to determine, if a moment falls into multiple time periods:

// ----------------------------------------------------------------------
public bool CheckDateBetweenDatesSample()
{
  DateTime now = DateTime.Now;
  TimePeriodCollection periods = new TimePeriodCollection();
  // read periods (Start/end) from database
  // ...
  periods.Add( new TimeRange( start, end ) );
  return periods.HasIntersectionPeriods( now );
} // CheckDateBetweenDatesSample
  • This library is a nice DT encapsulation:) @Jani I noted that you may not want to use a Collection class for checking one time. ITimePeriod.HasInside() can do the trick. – Antony Thomas Aug 31 '12 at 14:58
  • @Nick Just for your information that this library also uses `DateTime` for computation because that is the only way you can tell a time period. If you use just the TimeStamp, as in your OP, you will not know the difference between **10:30 AM of Aug-31-2012 and 10.30 AM of Aug-31-1900 ?** – Antony Thomas Aug 31 '12 at 15:01
  • @Anthony Many thanks. ITimePeriod.HasInside() was also my first intention. I used the Collection because many schedules are possible (Nick's comment on Konstatin's answer). –  Sep 01 '12 at 06:22
  • @Jani But the catch is that all the schedules(time-periods) should be treated as different entities. On the contrary, the collection would combine all its elements and create a big time period for which the . HasIntersectionPeriods() would be computed. – Antony Thomas Sep 01 '12 at 17:47
  • @Anthony That would be the case with `TimePeriodCollection.HasInside`. `TimePeriodCollection.HasIntersectionPeriods` iterates through all containing time periods. –  Sep 03 '12 at 06:43
0

Try this, its working for me. Correct me if i'm wrong.

TimeSpan timeOfDay = DateTime.Now.TimeOfDay;
TimeSpan startTimeToD = startTime.TimeOfDay;
TimeSpan endTimeToD = endTime.TimeOfDay;

if (timeOfDay > startTimeToD || timeOfDay < endTimeToD )
{
      Console.WriteLine("Hello World");
}

timeOfDay = new TimeSpan(2, 30, 00); //testcase
if (timeOfDay > startTimeToD || timeOfDay < endTimeToD )
{
     //will never execute.
}
VIRA
  • 1,454
  • 1
  • 16
  • 25
  • Start and end time is coming from database, so I can't get it like the way you suggested. Moreover, there r many schedules which needs to be run, and all have different Start and End time – Developer Aug 31 '12 at 05:02
  • @Raj You're using `Or` operator while you should have `And`...if your code looked like `if (timeOfDay > startTime && timeOfDay < endTime)` it wouldn't work for you – horgh Aug 31 '12 at 05:13
  • now check it, i just pasted the logic. It should be working for all the start time and end time. – VIRA Aug 31 '12 at 05:14
  • @konstanin, I have reversed his logic. ie he have checked 3.30AM to next day 1.30 AM. But i checked, if its not lying between 1.30 to 3.30 AM. – VIRA Aug 31 '12 at 05:16
  • You are still checking whether the task start time has come **or** the end time has not become...please, be attentive – horgh Aug 31 '12 at 05:21
  • Ah, i got it. Reverse logic would be like this, but the above should also be working fine. Reverse Logic: if (!(timeOfDay > endTimeToD && timeOfDay < startTimeToD)) { – VIRA Aug 31 '12 at 05:26
  • I didn't say to negate it, your **!** negation is superfluous...and the *above* should not work and wouldn't – horgh Aug 31 '12 at 05:29
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/16070/discussion-between-raj-and-konstantin-vasilcov) – VIRA Aug 31 '12 at 05:31
0

You cannot use TimeOfDay property as it is the absolute distance(elapsed time) from a midpoint(Midnight). What is wrong with using just DateTime for comparison? Comparison operators( < > <= >=) work perfectly fine with DateTime datatype.

For Eg:

DateTime currentTime = DateTime.Now;
DateTime startTime = DateTime.AddMinutes(-50D); //in your case this would be a DT todaysJob.STARTTIME.Value
DateTime endTime = DateTime.AddMinutes(50);// in your case this would be a DT todaysJob.ENDTIME.Value

if(currentTime > startTime && currentTime <= endTime)
{
  Console.Write("Works Fine"); //your logic
}
Antony Thomas
  • 3,576
  • 2
  • 34
  • 40
  • You missed the very beginning of this post))) The OP said that he's got only TimeSpan in his database – horgh Aug 31 '12 at 05:33
  • That does not add up. TimeSpan is just an interval,so what is the basetime that is used to calculate this TimeSpan ?? If you use Midnight, then 3.30pm should be a -ve TimeSpan and 1.30AM should be a +ve TimeSpan. – Antony Thomas Aug 31 '12 at 05:44
  • OP's got to mark the date of the task, because the time component reflects to 24 hours a day and it doesn't know anything about the date...so morning of tomorrow equals today's morning and your condition won't work as th OP needs it to check, if task starts today and ends sometime tomorrow – horgh Aug 31 '12 at 05:45
  • @KonstantinVasilcov Also, TimeSpan cannot have a TimeOfDay property as mentioned in the OP. Either the OP is wrong or our Understanding is wrong. – Antony Thomas Aug 31 '12 at 05:46
  • I guess he may have DateTime with 00.00.000 in his Date part of DateTime variables...He was already said to check the issue you mentioning – horgh Aug 31 '12 at 05:50
  • I am using oracle datebase, and the datatype of the column is TimeStamp, but since I am using EF, that property is coming as DateTime. But I am not using the date part, only time part. – Developer Aug 31 '12 at 06:36
  • I am confused. If you have a DateTime why don't you just use DateTime for comparison. Why do you want to use only the time part and created a seemingly convoluted logic. Not sure if I am missing something. – Antony Thomas Aug 31 '12 at 14:41