in reply to Check if Date interval contains Hour X

Um... according to your pseudocode, there should be 10 lines of output, because you seem to want to output one line for each of your two "hour" values tested against each of the 5 lines of input data. And in that regard, wouldn't it be helpful for the output to mention which of the "hour" values was being tested each time, and what time span it was being tested against?

As for the overall approach, I'm with ikegami (with some minor alterations): in order to make this workable in a general way, what you really want is a subroutine that takes three args: a targeted hour, and the start and end date/time values to test. A little sanity checking on the data would be worthwhile as well, and in case it counts for anything, there are some short-cuts you can take advantage of...

#!/usr/bin/env perl use strict; use Date::Calc qw/Date_to_Time/; sub hour_in_span { my ( $hr, $bgn, $end ) = @_; return unless ( $hr =~ /^\d{1,2}$/ and $hr >= 0 and $hr <= 23 ); my $hr2 = sprintf( "%02d", $hr ); # make sure to use 2 digits for ( $bgn, $end ) { return unless ( /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/ ); } return unless $bgn le $end; # require that args be in correct seq +uence # easiest case: start == end == hour of interest if ( $bgn eq $end ) { return ( $bgn =~ / $hr2:/ ); } # next easiest: span from start to end >= one full day # so it must include hour of interest my $ep_bgn = Date_to_Time( split /\D/, $bgn ); my $ep_end = Date_to_Time( split /\D/, $end ); return 1 if (( $ep_end - $ep_bgn ) / ( 24 * 60 * 60 ) >= 1 ); # hardest case: # -- plug hour of interest into each endpoint of the span # and see if either resulting time stamp falls within the span ( my $test_bgn = $bgn ) =~ s/ \d{2}:/ $hr2:/; ( my $test_end = $end ) =~ s/ \d{2}:/ $hr2:/; my $test_ep_bgn = Date_to_Time( split /\D/, $test_bgn ); my $test_ep_end = Date_to_Time( split /\D/, $test_end ); return (( $ep_bgn <= $test_ep_bgn and $ep_end >= $test_ep_bgn ) or ( $ep_bgn <= $test_ep_end and $ep_end >= $test_ep_end )); } ## End of algorithm ## -- from here on down, we're just testing it my @hours = ( 1, 11 ); while (<DATA>) { next unless ( /^\d{4}-/ ); my ( $bgn, $end ) = split /\|/; for my $hr ( @hours ) { my $in = hour_in_span( $hr, $bgn, $end ); if ( !defined( $in )) { print "$bgn -- $end / $hr : bad data\n"; } elsif ( $in ) { print "$bgn -- $end / contains $hr\n"; } else { print "$bgn -- $end / does NOT contain $hr\n"; } } } __DATA__ Start_Time | End Time | TEXT 2009-07-22 08:00:00|2009-07-22 08:00:00|blablalblabla 2009-07-22 01:00:00|2009-07-22 01:00:00|blablalblabla 2009-07-22 08:00:00|2009-07-22 21:00:00|blablalblabla 2009-07-22 23:00:00|2009-07-23 00:00:00|blablalblabla 2009-07-22 23:00:00|2009-07-23 02:00:00|blablalblabla

(BTW: you could relax the constraint on having the subroutine args in a specified order. So long as the "targeted hour" arg is in the right place, the other two args are interchangeable; just use the lower value as $bgn and the higher one as $end.)

Replies are listed 'Best First'.
Re^2: Check if Date interval contains Hour X
by gulden (Monk) on Jul 24, 2009 at 09:42 UTC
    «Um... according to your pseudocode, there should be 10 lines of output, because you seem to want to output one line for each of your two "hour" values tested against each of the 5 lines of input data. And in that regard, wouldn't it be helpful for the output to mention which of the "hour" values was being tested each time, and what time span it was being tested against?»
    u r right.