dtharby has asked for the wisdom of the Perl Monks concerning the following question:

Monks... I have a situation where I need to check that a time, say 22:40 is between a start (22:00) and end time(04:00) set in a db record.
I have tried every trick and I cannot get this to work (mainly been using if..elsif statements).
Can anyone give me some hints as to how to achieve this ?
Thanks, Danny

Replies are listed 'Best First'.
Re: Check Time between 2 other times
by sauoq (Abbot) on Nov 03, 2005 at 10:32 UTC

    How is the time stored? Is it just a time, or is there a date as well? Or will you always be working with times from the same date?

    You might find Time::Local useful to change your times back to seconds since the epoch. Once there, this is just a couple numerical comparisons.

    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Check Time between 2 other times
by terce (Friar) on Nov 03, 2005 at 11:38 UTC
    I realise it's not a Perl answer, but if you're getting the record from a database you may find that the database engine can do this work for you.
    AFAIK, all the major platforms include functions to allow you to compare, add and subtract dates/times.
    A simple query like
    select 1 where $my_date_time > $start_date_time and $my_date_time < $end_date_time
    might be sufficient.
    If your database record stores only times, not dates/times, you might get some mileage from looking into your database platform's commands for adding hours/minutes to the current time.

    A second, perhaps equally unhelpful suggestion:
    As you've doubtless discovered, 22:40 may or may not be between 22:00 and 04:00, depending on whether or not you infer 'on the same day'. If it's within your power to do so, perhaps it might be a good idea to alter the way the start/end times are stored in the database - perhaps storing the start time in conventional 24h clock notation(22:00), but then showing the duration of the task by specifiying a number of minutes (or hours, or nanoseconds - whatever unit suits best) after the start.
    So, instead of
    start | end ----------- 22:00 | 04:00
    you'd have
    start | end_after_minutes ---------------- 22:00 | 360
    Not only would it then be straightforward to calculate the start and end datetime values in the database (and so carry out the comparison you're after), but you'd also be able to specify tasks which last for more than 24 hours.
      select 1 where $my_date_time > $start_date_time and $my_date_time < $end_date_time

      That’s un-SQLish. It can be better written as

      SELECT 1 WHERE $my_date_time BETWEEN $start_date_time AND $end_date_time

      (And of course, you’d pass the values in using placeholders, not by interpolating them into the SQL.)

      Makeshifts last the longest.

        Absolutely, on both points. I was trying to make the logic as clear as possible for the OP.

        (also, I'm not sure whether all SQL dialects support BETWEEN)
Re: Check Time between 2 other times
by allyc (Scribe) on Nov 03, 2005 at 13:15 UTC

    You could try Date::Calc as it has some good functions for comparing Time / Dates. I have used it many times.

    Might be something that will help you in there.

    The other thing that you could try is to convert the Date / Time into Epoc seconds which I find much easier to then run checks on.

    Al

Re: Check Time between 2 other times
by hubb0r (Pilgrim) on Nov 04, 2005 at 06:19 UTC

    My guess is that you also have a date field in the database for the record time. If you do, then I would convert the date/time to unixtime and then do the comparison:

    use HTTP::Date; my $start_time = str2time('2005-10-01 22:00:00'); my $end_time = str2time('2005-10-02 04:00:00'); my $check_time = str2time('2005-10-01 22:40:00'); if ($start_time < $end_time) { if ($start_time < $check_time and $check_time < $end_time) { print "yes\n"; } else { print "no\n"; } } elsif ($end_time < $start_time) { if ($end_time < $check_time and $check_time < $start_time) { print "yes\n"; } else { print "no\n"; } } else { print "Start and End times are identical\n"; }

    For the sake of clarity, I left out retrieving the db times and left them as strings. Also, as others have pointed out, this is easily doable in the db with a simple SQL query:

    SELECT 1 WHERE check_time BETWEEN start_time AND end_time or SELECT 1 WHERE concat(check_date, ' ', check_time) BETWEEN concat(star +t_date, ' ', start_time) AND concat(end_date, ' ', end_time)
    </code>
Re: Check Time between 2 other times
by davidrw (Prior) on Nov 03, 2005 at 14:04 UTC
    What are you if..elsif attempts? There are two cases -- one where start<=end and the other where end<start (the "overnight" window, where 10pm is before 4am). Here is pseudocode for an if ladder:
    # WARNING -- it's left to the reader to properly compare the values (c +an't do '01:40' < '01:30') if start <= end return 1 if start <= t and t <= end else # end < start return 1 if ( start <= t and t <= 23:59 ) or ( 00:00 <= t and t <= +end ) endif