Here's an example of how to accomplish this:
use List::Util qw/min max/;
my %results = map {
my $year_ref = $data{$_};
my $min = min values %$year_ref;
my $max = max values %$year_ref;
my @min_months = grep { $year_ref->{$_} == $min } keys %$year_ref;
my @max_months = grep { $year_ref->{$_} == $max } keys %$year_ref;
$_ => {
"min" => $min,
"max" => $max,
"min_months" => \@min_months,
"max_months" => \@max_months
}
} keys %data;
Note that this takes into account the possibility of there being several months that each have the minimum/maximum value; if your data for each year/month is guaranteed to be distinct, you could drop that and replace \@min_months with $min_months[0] and \@max_months with $max_months[0], respectively.
There may well be a more concise way of doing this, too, but neither List::Util nor List::MoreUtils appears to contain versions of min and max that operate on key/value pairs (pairmin and pairmax? Now there'd be a worthwhile addition to these modules.)