use Time::Local; ... for my $row (@rows) { my @l = reverse split /-/, $row->{start_date}; $l[1]--; # months range is 0..11 my $key = timelocal(0,0,0,@l); my $line = join("\t", $row->{id_number}, $row->{start_time}); # whatever formatting if(split/:/,$row->start_time)[0] > 9) { push @{$hash{$key-86400}}, $line; } else { push @{$hash{$key}}, $line; } } foreach my $key (sort %hash) { my @l = (localtime $key)[5,4,3]; $l[1]++; # month... print join('-', @l), "\n"; print $_,"\n" for @{$hash{$key}}; }