in reply to Finding gaps in date ranges

An old tactic when faced with a representation that has a lot of boundary cases. Convert to and from a representation that is easier to work with, like so:
use strict; use Carp; # Takes a list of months in yyyymm format, returns the gaps in sorted +order. sub find_gaps { my @dates = sort {$a <=> $b} map {yyyy_mm2mon_num($_)} @_; my $last_mon_count = shift @dates; my @gaps; foreach my $mon_count (@dates) { foreach my $missed (($last_mon_count + 1)..($mon_count-1)) { push @gaps, mon_num2yyyy_mm($missed); } $last_mon_count = $mon_count; } return @gaps; } # Converts a count of months back into yyyymm format sub mon_num2yyyy_mm { my $mon_num = shift; use integer; my $yyyy = $mon_num / 12; my $mm = 1 + $mon_num % 12; # Sanity check unless (1900 < $yyyy and $yyyy < 2200) { carp("Month number '$mon_num' gives a year of $yyyy which seems st +range"); } return "$yyyy-$mm"; } # Converts yyyymm format into a count of months from year 0. (Which d +idn't # exist, shoot me. It is a convenient base-point for calculations.) sub yyyy_mm2mon_num { my $date = shift; if ($date =~ /(\d{4}).*?(\d\d?)/) { return 12*$1 + $2 - 1; } else { confess("Date '$date' is not in yyyymm format?"); } }

Replies are listed 'Best First'.
(Ovid - nice try)Re: Re (tilly) 1: Finding gaps in date ranges
by Ovid (Cardinal) on May 11, 2001 at 00:57 UTC
    The reference to @_ in find_gaps should actually be keys %{ $_[0] }. From there, I ran it with the following dates (first line of dates from my test suite):
    2000-4 2000-2 2000-1 2000-12 2001-1 2002-12 1999-12
    The output:
    $VAR1 = '2000-3';
    It found the first gap but not the rest.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Ick, that API looks ugly. For the sake of having a clean API I would stick with my current function and call keys on the way into the function, not inside of it.

      That said, you must have changed more than one thing in your test run. When I run it, here is what I get:

      # The test code: print map "$_\n", find_gaps( qw(2000-4 2000-2 2000-1 2000-12 2001-1 2002-12 1999-12) ); # The output 2000-3 2000-5 2000-6 2000-7 2000-8 2000-9 2000-10 2000-11 2001-2 2001-3 2001-4 2001-5 2001-6 2001-7 2001-8 2001-9 2001-10 2001-11 2001-12 2002-1 2002-2 2002-3 2002-4 2002-5 2002-6 2002-7 2002-8 2002-9 2002-10 2002-11