App-Chart
view release on metacpan or search on metacpan
lib/App/Chart.pm view on Meta::CPAN
#------------------------------------------------------------------------------
sub ymd_to_iso {
my ($year, $month, $day) = @_;
return sprintf ('%04d-%02d-%02d', $year, $month, $day);
}
sub iso_to_ymd {
my ($iso) = @_;
return split /-/, $iso;
}
sub adate_to_ymd {
my ($adate) = @_;
return Date::Calc::Add_Delta_Days(1970,1,5, $adate);
}
my $adate_days_base = Date::Calc::Date_to_Days (1970, 1, 5);
sub ymd_to_adate {
my ($year, $month, $day) = @_;
return Date::Calc::Date_to_Days($year, $month, $day) - $adate_days_base;
}
sub adate_to_iso {
my ($tdate) = @_;
return App::Chart::ymd_to_iso (App::Chart::adate_to_ymd ($tdate));
}
sub tdate_to_ymd {
my ($tdate) = @_;
return adate_to_ymd (tdate_to_adate ($tdate));
}
sub tdate_to_iso {
my ($tdate) = @_;
return adate_to_iso (tdate_to_adate ($tdate));
}
sub tdate_to_adate {
my ($tdate) = @_;
return $tdate + floor ($tdate/5)*2;
}
sub adate_to_tdate_floor {
my ($adate) = @_;
return floor ($adate / 7) * 5 + min ($adate % 7, 4);
}
sub adate_to_tdate_ceil {
my ($adate) = @_;
return floor ($adate / 7) * 5 + min ($adate % 7, 5);
}
sub ymd_to_tdate_floor {
my ($year, $month, $day) = @_;
return adate_to_tdate_floor (ymd_to_adate ($year, $month, $day));
}
sub ymd_to_tdate_ceil {
my ($year, $month, $day) = @_;
return adate_to_tdate_ceil (ymd_to_adate ($year, $month, $day));
}
#------------------------------------------------------------------------------
sub collapse_whitespace {
my ($str) = @_;
$str =~ s/\x{A0}+/ /g; # latin1/unicode non-breaking space
$str =~ s/$RE{ws}{crop}//g; # leading and trailing whitespace
$str =~ s/\s+/ /g; # middle whitespace
return $str;
}
#------------------------------------------------------------------------------
sub decimal_sub {
my ($x, $y) = @_;
# would prefer an actual decimal-arithmetic subtract here
my $decimals = max (count_decimals($x), count_decimals($y));
return sprintf ('%.*f', $decimals, $x - $y);
}
#------------------------------------------------------------------------------
sub count_decimals {
my ($str) = @_;
my $pos = index ($str, '.');
if ($pos >= 0) {
return length($str) - $pos - 1;
} else {
return 0;
}
}
#------------------------------------------------------------------------------
# Return min or max of the arguments, ignoring any undefs.
# If no args (no undefs that is) then return undef.
# List::Util min() and max() return undef for no args, but they want all args
# to be numeric.
#
sub min_maybe {
return min (grep {defined} @_);
}
sub max_maybe {
return max (grep {defined} @_);
}
#------------------------------------------------------------------------------
# App::Chart::datafilename ($filename)
# App::Chart::datafilename ($dir,...,$dir, $filename)
#
# Return an absolute path like /usr/share/perl5/App/Chart/$filename,
# wherever App/Chart/$filename is found in @INC. $dir arguments specify a
# subdirectory like App/Chart/$dir1/$dir2/$filename. All args and the
# return are in filesystem charset bytes.
#
# Module::Find and Module::Util have similar @INC searches, but only for .pm
# files it seems.
#
sub datafilename {
foreach my $inc (@INC) {
my $filename = File::Spec->catfile ($inc, 'App', 'Chart', @_);
if (-e $filename) { return $filename; }
}
require File::Basename;
return File::Spec->catfile (File::Basename::dirname($INC{'App/Chart.pm'}),
( run in 0.822 second using v1.01-cache-2.11-cpan-d7f47b0818f )