in reply to Help with GD::Graph
# format a set of dates for display on the X axis sub dates_to_header { my ($self, $dates) = @_; my @header = ("") x scalar @$dates; # choose a format based on the length of the range my $delta = $dates->[-1]->subtract_datetime($dates->[0]); my $months = $delta->delta_months; my $days = $delta->delta_days + ($months * 30); # rough guess is + ok here my ($format, $number); if ($months >= 5 and $months <= 11) { $format = "%b"; # month abrev $number = $months + 1; } elsif ($days <= 1) { $format = "%l %p"; # HH AM/PM $number = 5; } elsif ($days <= 6) { $format = "%a"; # weekdays, mark them all $number = @$dates; } elsif ($dates->[0]->year eq $dates->[-1]->year) { $format = "%m/%d"; # MM/DD $number = 5; } else { $format = "%D"; # MM/DD/YYx $number = 5; } if ($number == @$dates) { # marking all bars return [map { $_->strftime($format) } @$dates]; } # find the optimal spacing between labels my $spacing = @$dates / ("$number.0" - 1); # place a label at the edges my @spots = (0, $#$dates); # if there are odd numbers of dates to place, put one in the cente +r my $center = int(@$dates / 2); push(@spots, $center) if $number % 2; # place the remaining dates around the center, following the spaci +ng for (1 .. (($number - @spots) / 2)) { push(@spots, $center + int($spacing * $_)); push(@spots, $center - int($spacing * $_)); } # render the date at each chosen spot foreach my $spot (@spots) { $header[$spot] = $dates->[$spot]->strftime($format); } return \@header; }
That subroutine takes a reference to an array of DateTime objects representing the data-points on the graph. It then applies a bunch of heuristics to come up with some reasonable labels for the X axis, leaving enough space for them to render successfully.
Hope that helps.
-sam
|
|---|