http://www.perlmonks.org?node_id=1006963

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

I have a script which takes two arguments. A start datetime and and end datetime.
script.pl --start ’Oct 10 05:50:’ --end ’Oct 10 05:5[0-2]:’
The script then does a binary search to the first occurrence of --start... and prints lines until it reaches --end. I'd like to make this a bit more user friendly. Mainly by not making the use enter a regex as --end. And instead taking a datetime Oct 10 05:59:59 and automatically creating a regex from it.. Is it possible to do this?

Replies are listed 'Best First'.
Re: dynamic regex
by graff (Chancellor) on Dec 04, 2012 at 00:16 UTC
    If you want to use a regex like Oct 10 05:5[0-2]:, then I'd say you don't need "start" and "end" values, because the desired range from start to end is fully expressed in that one regex.

    If the intent of your example is to catch everything between "Oct 10 05:50:00" and "Oct 10 05:52:59" inclusive, then a logical two-arg, start/end spec would look like this (which would be pretty simple for any naive user to understand):

    script.pl --start 'Oct 10 05:50 --end 'Oct 10 05:52'
    (Including specific seconds values in the start and/or end options would also be simple.)

    Depending on what kind of data the script is going to do its "binary search" over, it might be more sensible to use one of the Date:: modules, to interpret both the user's ARGV values and the date values in the data being searched - i.e. something like:

    my $user_start_date = get_secs_from_opt( $opt{start} ); my $user_end_date = get_secs_from_opt( $opt{end} ); for my $record ( @data_records ) { my $rec_date = get_secs_from_data( $record ); if ( $rec_date >= $user_start_date and $rec_date <= $user_end_date + ) { # do something with a hit... } }
    The "get_secs_from_*" functions would just invoke some suitable Date:: module to return "unix_time" (or whatever term is used for "seconds since the epoch" in the chosen module).

    But then, I'm not sure what you mean by "binary search", so maybe this isn't helpful.

Re: dynamic regex
by LanX (Saint) on Dec 03, 2012 at 23:44 UTC
    I don't understand which logic leads from 'Oct 10 05:59:59' to 'Oct 10 05:5[0-2]:'

    but yes, you can put a datetime-string into a variable, dynamically manipulate this variable and use it as a pattern within any regex.

    my $dt = 'Oct 10 05:59:59'; $dt =~ s/9:59$/[0-2]:/; $file =~ m/$dt/;

    HTH!

    Cheers Rolf

Re: dynamic regex
by Kenosis (Priest) on Dec 04, 2012 at 03:59 UTC

    I agree with graff about using a Date:: module. How would you create the end given this start?

    script.pl --start 'Dec 31 23:59'

    Consider the following:

    use strict; use warnings; use Date::Parse; use Date::Calc qw/Localtime/; my $startDateTime = 'Dec 31 23:59:'; my $addMinutes = 2; my $year = ( Localtime(time) )[0]; $startDateTime .= '00 ' . $year; my $startSeconds = str2time($startDateTime); my $endSeconds = $startSeconds + $addMinutes * 60; print "\$startSeconds: $startSeconds; \$endSeconds: $endSeconds; Delta +: " . ( $endSeconds - $startSeconds );

    Output:

    $startSeconds: 1357027140; $endSeconds: 1357027260; Delta: 120

    You can use Date::Parse to convert a line's date/time string to seconds, and then print the line if the value's within the $startSeconds and $endSeconds range.