开发者

Determine if time falls in designated hour range

I am new at C#. I'd like to check whether a time is between 2 given hours, and if so then do something. Can anyone give me an example?

pseudocode example:

int starthour = 17;
int endhour = 2;

if ( hour between starthour and endhour){
    dosomething();
}

How do I write a check on whether hour is between starthour and endhour? In C#, the time is returned in AM/PM format so I don't know if it will understand the 17 number开发者_运维百科 as "5 PM".


Assuming you're talking about the current time, I'd do something like this:

// Only take the current time once; otherwise you could get into a mess if it
// changes day between samples.
DateTime now = DateTime.Now;
DateTime today = now.Date;
DateTime start = today.AddHours(startHour);
DateTime end = today.AddHours(endHour);

// Cope with a start hour later than an end hour - we just
// want to invert the normal result.
bool invertResult = end < start;

// Now check for the current time within the time period
bool inRange = (start <= now && now <= end) ^ invertResult;
if (inRange)
{
    DoSomething();
}

Adjust the <= in the final condition to suit whether you want the boundaries to be inclusive/exclusive.

If you're talking about whether a time specified from elsewhere is within a certain boundary, just change "now" for the other time.


Actually, if we're dealing with pure hours here like a Abelian Ring from 0 to 23 and 0 again, I believe the following is actually a working solution:

(start <= end && start <= t && t <= end) or (start > end && (start <= t || t <= end))

Complex though this is, it is essentially an if-else where you have a different algorithm depending on whether start <= end or not, where t is the time you wish to test. In the first case, start and end are normal order, so t must be both greater than start and less than end. In the case where start is greater than end, the times outside the opposite range are what we want:

  • NOT(end < t and t < start)

Using DeMorgan's theorem:

  • NOT(end < t) or NOT(t < start)
  • NOT(t < start) or NOT(end < t)
  • t >= start or end >= t
  • start <= t or t <= end

This should solve your and my problems.

@JonSkeet

The thing is, looking at your algorithm, let's assume for a moment the time is 1am, day 1.

  • Now holds 1am Day 1
  • Today holds midnight Day 1
  • Start holds 5pm Day 1 (given the original example)
  • End holds 2am Day 1 (again from the example)
  • End holds 2am Day 2 (since start > end)

Now, unless I'm mistaken, start ≰ now since start is 5pm Day 1 and now is 1am Day 1 which is before now, therefore the test fails but the original question wanted 1am included in the range since 1am is between 5pm and 2am. Did I miss something?

@Brian

Also, looking at your code, I think you can detect 1am but now you would have a problem with 10pm (22:00) since your times become:

  • Start is 17
  • End is 26
  • Now is 22 + 24 = 46! so you will fail in the less-than test.

Clearly, the general case is very tricky! More so when you're restricted to Google Spreadsheets as I am.


When subtracting DateTimes, you get a TimeSpan struct that you can query for things like the total number of hours (the TotalHours property):

TimeSpan ts = starttime - endtime;
if(ts.TotalHours > 2)
{
  dosomething();
}

If you want to see if the times are identical, then you can use TotalMilliseconds - for identical DateTimes, this will be equal to 0.


If you want to compare minutes also like I do you can use this snippet of code in java.

        //Initialize now, sleepStart, and sleepEnd Calendars
        Calendar now = Calendar.getInstance();
        Calendar sleepStart = Calendar.getInstance();
        Calendar sleepEnd = Calendar.getInstance();

        //Assign start and end calendars to user specified star and end times
        long startSleep = settings.getLong("startTime", 0);
        long endSleep = settings.getLong("endTime", 0);
        sleepStart.setTimeInMillis(startSleep);
        sleepEnd.setTimeInMillis(endSleep);

        //Extract hours and minutes from times
        int endHour = sleepEnd.get(Calendar.HOUR_OF_DAY);
        int startHour = sleepStart.get(Calendar.HOUR_OF_DAY);
        int nowHour = now.get(Calendar.HOUR_OF_DAY);
        int endMinute = sleepEnd.get(Calendar.MINUTE);
        int startMinute = sleepStart.get(Calendar.MINUTE);
        int nowMinute = now.get(Calendar.MINUTE);

        //get our times in all minutes
        int endTime = (endHour * 60) + endMinute;
        int startTime = (startHour * 60) + startMinute;
        int nowTime = (nowHour * 60) + nowMinute;

    /*****************What makes this 100% effective***************************/
        //Test if end endtime is the next day
        if(endTime < startTime){
            if(nowTime > 0 && nowTime < endTime)
                nowTime += 1440;
            endTime += 1440;
        }
    /**************************************************************************/

        //nowTime in range?
        boolean inRange = (startTime <= nowTime && nowTime <= endTime);

        //in range so calculate time from now until end
        if(inRange){
            int timeDifference = (endTime - nowTime);
            now.setTimeInMillis(0);
            now.add(Calendar.MINUTE, timeDifference);
            sleepInterval = now.getTimeInMillis() / 1000;
            editor.putBoolean("isSleeping", true);
            editor.commit();
            Log.i(TAG, "Sleep Mode Detected");
            returned = true;
        }


bool CheckHour(DateTime check, DateTime start, DateTime end)
{
    if (check.TimeOfDay < start.TimeOfDay)
        return false;
    else if (check.TimeOfDay > end.TimeOfDay)
        return false;
    else
        return true;
}


int starthour = 17;
int endhour = 2;
int nowhour = DateTime.Now.Hour;

if (endhour < starthour)
{
    endhour+=24;
    nowhour+=24;
}

if (starthour <= nowhour && nowhour <= endhour)
{
    dosomething();
}

I'm not sure which I prefer between this code and Jon Skeet's code.


Using Jon Skeet's solution above I added a fix where if start time is after beginning time eg You start the job after 6pm at night and end it the next morning at 5am. then you need to check this and apply another day to the end time. Hope it helps, I personally have spent too much time on this piece of work. have a great day :)

if (stopHour < startHour)
{
end = today.AddHours(stopHour+24);
}

Full Code is below.

private static bool IsInRunHours()
{
        try
        {
            ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).Save(ConfigurationSaveMode.Modified);
            ConfigurationManager.RefreshSection("appSettings");
            // after = 18 before = 5

            // Only take the current time once; otherwise you could get into a mess if it
            // changes day between samples.
            DateTime now = DateTime.Now;
            DateTime today = now.Date;

           Int32 startHour = ConfigurationManager.AppSettings["UpdateRunAfter"].ToInt();
            Int32 stopHour = ConfigurationManager.AppSettings["UpdateRunBefore"].ToInt(); 


            DateTime start = today.AddHours(startHour);
            DateTime end = today.AddHours(stopHour);

            if (stopHour < startHour)
            {
                 end = today.AddHours(stopHour+24);

            }


            //ConfigurationManager.AppSettings["UpdateRunBefore"].ToInt()
            //ConfigurationManager.AppSettings["UpdateRunAfter"].ToInt()
            // Cope with a start hour later than an end hour - we just
            // want to invert the normal result.
            bool invertResult = end < start;

            // Now check for the current time within the time period
            bool inRange = (start <= now && now <= end) ^ invertResult;
            if (inRange)
            {
                return true;
            }
            else
            {
                return false;
            }



        }
        catch
        {
            return false;
        }

    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜