http://qs321.pair.com?node_id=763756

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

When I see a certain condition (I.e. a file is written in a directory) I need to perform an action. I am wanting to check that the current time (I.e. now) is between certain dates and times and if so I will NOT perform this action. So this is a simple exclusion\blackout list and I identify which config element to use based on criteria in the file that I have read from the dir. The configuration is in xml and looks as follows
<!--MyExample_1 will not perform any action between 1st January 2006 1 +2 noon and 2nd March 2006 12 noon--> <resource name="MYEXAMPLE_1" start="01-01-2006 12:00" end="02-03-2006 +12:00"></resource> <!--MyExample_1b does NOT have an end time defined so from the Start t +ime for evermore NO actions will be performed--> <resource name="MYEXAMPLE_1B" start="01-01-2006 12:00" end=""></resour +ce> <!--MyExample_2 will not perform any actions between 7 PM and 9 PM eve +ry day. every stands for all days (IE MON - SUN)--> <resource name="MYEXAMPLE_2" start="every 19:00" end="every 21:00"></r +esource> <!--MyExample_3 will never perform ANY actions --> <resource name="MYEXAMPLE_3" start="" end=""></resource>
What I do is convert the start time to epoch and then the end time to epoch and check if the current epoch is between these two times. I have a method that looks as follows:
#--------------------------------------------------------------------- +------------------ # Convert supplied date to Epoch time #--------------------------------------------------------------------- +------------------ sub toEpoch { my $date = shift; my ($epoch, @suppliedTime, @suppliedDate); my @tempdate = split/\s/, $date; @suppliedTime = split/:/, $tempdate[1]; if (uc($tempdate[0]) eq "EVERY") { #print "\t\t**This will return the epoch to this time TODAY**\ +n"; $epoch = timelocal(0, $suppliedTime[1], $suppliedTime[0], (loc +altime)[3], (localtime)[4], ((localtime)[5]+1900)); } else { @suppliedDate = split/-/, $tempdate[0]; $epoch = timelocal(0, $suppliedTime[1], $suppliedTime[0], $sup +pliedDate[0], ($suppliedDate[1] - 1), $suppliedDate[2]); } return($epoch); }

Obviously, if there is no end time, or no start and no end time, I handle that accordingly (see the config xml comments). You will also see in the toEpoch function if the word "every" is received as the first element in the configured date that is passed from the configuration I check only the times i.e. start time and end time for each and every day.

So far this rudimentary way of handling the checking if the current time falls between two configurable exclusion\blackout times has worked well. However, some-one has now asked that we exclude/blackout processing the actions every Monday. I now have to come up with a way of identifying if it is Monday between the times in the config and if say it is Tuesday perform the action. however if it is any Monday between the defined times do not perform the action. I would like the configuration to look as follows;

<!--MyExample_2 will not perform any actions between 7 PM and 9 PM eve +ry Monday.--> <resource name="MYEXAMPLE_2" start="mon 19:00" end="mon 21:00"></resou +rce>
This I can get (I think) by getting (localtime)[6] and checking
my $configuredDayFromXML = "mon"; #obtain from configuration my @daysOfWeek = ('Sun', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'); if ($configuredDayFromXML eq $daysOfWeek[(localtime)[6]]) { if (! check if we are between the start and end time) { perform action; } }
The problem I am trying to rack my head around is, if I want to configure a blackout period of say between "Mon 11:00" and "Wed 11:30" how would I identify the epoch time and how would I check between say "Fri 16:00" and "Mon 8:00" (I.e. nothing over the weekend).

I hope this explanation has not proved to be too tiresome. Regards AcidHawk

-----
Of all the things I've lost in my life, its my mind I miss the most.

Replies are listed 'Best First'.
Re: Check current time between range of dates and times
by wjw (Priest) on May 13, 2009 at 14:02 UTC
    I would check out the Date::Calc module from CPAN

    Date::Calc

    I don't know if it has a function that does exactly what you are trying to do, but it, or one of its sibling modules will get you close...

    addendum: This is available from ActiveState as well if that is your flavor...

    • ...the majority is always wrong, and always the last to know about it...
    • The Spice must flow...
    • ..by my will, and by will alone.. I set my mind in motion
      Yeah, thanks wjw I have looked (and still am looking) at Date::Calc and Date::Manip. However the logic is what I need more assistance on as apposed to what modules I need to use.

      Thanks though.

      -----
      Of all the things I've lost in my life, its my mind I miss the most.
        Sorry for the mis-understanding..., but this is an interesting problem to me.

        If you were to determine:

        • What week I am in
        • The epoch start and epoch end value of the week
        • The epoch start and epoch end of each blackout period within the current week

        perhaps place the epoch start ends in a HOL, then iterate through checking your that your current time is not between any of the start/end times in the hash.

        If I understand it right, you only want to check your current time against those in you xml file that have start and end times. The idea here is to collect all of them in one place in epoch format, check against each pair, and if now is not between any of them, do some action.

        But then I may be way off track here too.. .

        Thanks for posting the problem. It is related to some things I do every day with event based data, and it is good to try to see into a similar problem from a different perspective..

        • ...the majority is always wrong, and always the last to know about it...
        • The Spice must flow...
        • ..by my will, and by will alone.. I set my mind in motion
Re: Check current time between range of dates and times
by Marshall (Canon) on May 13, 2009 at 23:07 UTC
    Epoch time is the number of seconds +or- from the epoch and is a signed integer value of some precision x. It is possible to do "time math" in seconds on epoch times. Use date/time string to create an epoch time and then add 24*60*60 seconds to it to get 24 hours from then if you want 23.5 hours then add(or subtract) 24*60*60-(30*60)..keep things in whole numbers (don't use .3 for a third of a day, use 8 hours *60 min*60 sec, etc...

    So to see if your proposed date is in-between those times, convert it to epoch seconds also and do a numeric comparison.

    You can use the stat func to figure out if that proposed date is Monday in your local time.

    I would normally do everything in GMT or UTC as it is known today.

    Of course I may have missed something here...

    Update: oh, another point, when writing log files, etc. I use a format like this: 2007-10-06 1647. If leading zeroes are enforced for both date and time, then a simple alpha comparison or sort will get the right answer. To add 30 minutes to 2007-10-06 1647, I convert to epoch, add 30*60, then convert back to string (all this 24 hours, 60 minutes stuff is messy).