简体   繁体   中英

Is current time within range

I know this question has been asked manytimes but mine has a small twist. There are many different shifts at work and I have two string shiftStart and shiftEnd . (example "6:00:00 PM" & "03:00:00 AM" respectively). This represents noon to morning. I am trying to make a function which tells me if DateTime.Now is within this timeperiod.

Note: the shift can be anything ... morning to noon, noon to morning, no fixed duration (like 8 hours).

static bool NowWithinShiftTime("6:00:00 PM", "03:00:00 AM")

Following is what I have tried but no matter what I do I cannot seem to find the logic... Please help me out...

static bool NowWithinShiftTime(string shiftStart, string shiftEnd)
    {
        DateTime startDate;
        DateTime endDate;
        DateTime now = DateTime.Now; 

        TimeSpan startTime = DateTime.Parse(shiftStart).TimeOfDay;
        TimeSpan endTime = DateTime.Parse(shiftEnd).TimeOfDay;

        if (startTime < endTime) // same day
        {
            startDate = new DateTime(now.Year, now.Month, now.Day) + startTime;
            endDate = new DateTime(now.Year, now.Month, now.Day) + endTime;
        }
        else // next day
        {
            startDate = new DateTime(now.Year, now.Month, now.AddDays(-1).Hour) + startTime;
            endDate = DateTime.Today.AddDays(1) + endTime;
        }
        if (now >= startDate && now <= endDate)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

You could stick with TimeSpan :

static bool NowWithinShiftTime(string shiftStart, string shiftEnd)
{
    TimeSpan startTime = DateTime.Parse(shiftStart).TimeOfDay;
    TimeSpan endTime = DateTime.Parse(shiftEnd).TimeOfDay;
    TimeSpan now = DateTime.Now.TimeOfDay;

    if (startTime < endTime)
        return now >= startTime && now <= endTime;
    else
        return now >= startTime || now <= endTime;
}

Firstly, make all the business logic deal just with time-related types. (Personally I'd use my Noda Time library with its LocalTime type for this work, but...) The parsing can come in the calling code.

The logic is reasonably simple: if the "end time" is actually before the "start time" then just switch the two round and invert the result. After all, you're just dividing the day into "shift time" and "not shift time"... and a shift of (say) 8pm to 3am is "on" whenever a shift of 3am to 8pm is "off".

For example:

public bool NowWithinShiftTime(TimeSpan startTimeOfDay, TimeSpan endTimeOfDay)
{
    if (startTimeOfDay > endTimeOfDay)
    {
        return !NowWithinShiftTime(endTimeOfDay, startTimeOfDay);
    }
    TimeSpan now = DateTime.Now.TimeOfDay;
    return startTimeOfDay <= now && now < endTimeOfDay;
}

Notes:

  • I've made this deliberately half-closed, as that tends to be appropriate for intervals so that if you have abutting intervals, any given value falls into exactly one. Check exactly what you want, although it'll only be relevant for those two exact points in time per day.
  • The code is currently hard to test: I'd encourage you to abstract out the idea of "a clock" into an interface, so you can use a fake clock for testing. (Noda Time does this for you, and provides an appropriate FakeClock .)

I believe you're 90% there:

static bool NowWithinShiftTime(string shiftStart, string shiftEnd)
{
    DateTime startDate;
    DateTime endDate;
    DateTime now = DateTime.Now; 

    TimeSpan startTime = DateTime.Parse(shiftStart).TimeOfDay;
    TimeSpan endTime = DateTime.Parse(shiftEnd).TimeOfDay;

    if (startTime < endTime) // same day
    {
        startDate = DateTime.Today + startTime;
        endDate = DateTime.Today + endTime;
    }
    else // next day
    {
        startDate = DateTime.Today  + startTime;
        endDate = DateTime.Today.AddDays(1) + endTime;
    }
    if (now >= startDate && now <= endDate)
    {
        return true;
    }
    else
    {
        return false;
    }
}

Here's an ideone to show it works: http://ideone.com/rdb867

This should work

static bool NowWithinShiftTime(string shiftStart, string shiftEnd)
{
   DateTime now = DateTime.Now;
   DateTime startDate = DateTime.Parse(shiftStart);
   DateTime endDate = DateTime.Parse(shiftEnd);

   if (endDate < startDate)
   {
        endDate = endDate.AddDays(1);
   }

   return now >= startDate && now <= endDate;
}

This should work:

bool IsWithinTimeRange(DateTime dateToCompare, DateTime startDate, DateTime endDate)
{
    TimeSpan timeToCompare = dateToCompare.TimeOfDay;
    TimeSpan start = startDate.TimeOfDay;
    TimeSpan end = endDate.TimeOfDay;

    if (start < end)
        return timeToCompare >= start && timeToCompare <= end;
    else
        return !(end < timeToCompare && timeToCompare < start);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM