Filter by date method This method allows me to filter by date a data structure list of hash that contains articles. I would like to have your opinion on the code:

=method article_by_date

    $articles-&gt;articles_by_date( month =&gt; 12 );


Return a list of articles filter by date specified:

    input: month (Int) : optional, month to match
           year (Int) : optional, year to match
    output: Hashref: Details of article

=cut

sub articles_by_date {
    state $check = compile(
        $invocant,
        slurpy Dict[
            month =&gt; Optional[Int],
            year  =&gt; Optional[Int],
        ]
    );
    my ($self, $arg) = $check-&gt;(@_);
    my $month = $arg-&gt;{month};
    my $year  = $arg-&gt;{year};

    if ( ! defined($year) ) {
        my $dt = DateTime-&gt;now;
        $year  = $dt-&gt;year;
    }

    my $date  = defined($month)
        ? qr/^\d\d\/$month\/$year\s\d\d:\d\d:\d\d$/
        : qr/^\d\d\/\d\d\/$year\s\d\d:\d\d:\d\d$/;

    my @articles;
    foreach my $article ( @{$self-&gt;_get_or_create_cache('articles')} ) {
        $article-&gt;{date} =~ $date
            and push(@articles, $article);
    }

    return \@articles;
}
Most of this depends on what exactly do you want to achieve. For example, @articles will be a list of references to the same articles that are also referenced in $self-&gt;_get_or_create_cache('articles'). Depending on what you want, you might want to clone these values, instead of just pushing them to @articles.

The other thing is a regex for dates. Are you certain that your dates will be, for example, 23/08/2013, and not 23/8/2013? If not, this might be better:

my $date  = defined($month)
    ? qr/^\d{1,2}\/$month\/$year\s\d{1,2}:\d{1,2}:\d{1,2}$/
    : qr/^\d{1,2}\/\d{1,2}\/$year\s\d{1,2}:\d{1,2}:\d{1,2}$/;


The same goes for the times, of course.

Depending on how clean your input is, you might want to replace $month and $year with \Q$month\E and \Q$year\E to avoid matching special characters in those variables (i.e., that . is matched as a dot and not as any character).

If it may be possible for the input to have extra spaces, you might want to add \s* after ^ and before $, while also replacing \s behind $year with \s+.

Day of month can be more precisely matched as (0?[1-9]|[1-2]\d|3[01]) (similar for months, hours, minutes, and seconds), but this makes regexes quite comples, so see if you need this.