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 )