Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 10478553

Von Sven Schöling vor etwa 12 Jahren hinzugefügt

  • ID 10478553c500772a988036a69947a7e6d19d404e
  • Vorgänger f2d2aa73
  • Nachfolger 846c2f9e

Form::format_amount - suabere trennung zwischen String und Numerischen Kontexten

behebt #1982 (unter anderem)

Unterschiede anzeigen:

SL/Form.pm
866 866
  $main::lxdebug->enter_sub(2);
867 867

  
868 868
  my ($self, $myconfig, $amount, $places, $dash) = @_;
869
  $dash ||= '';
869
  $amount ||= 0;
870
  $dash   ||= '';
871
  my $neg = $amount < 0;
872
  my $force_places = defined $places && $places >= 0;
870 873

  
871
  if ($amount eq "") {
872
    $amount = 0;
873
  }
874

  
875
  $amount *= 1;
876

  
877
  # Hey watch out! The amount can be an exponential term like 1.13686837721616e-13
874
  $amount = $self->round_amount($amount, abs $places) if $force_places;
875
  $amount = sprintf "%.*f", ($force_places ? $places : 10), abs $amount; # 6 is default for %fa
878 876

  
879
  my $neg = ($amount =~ s/^-//);
880
  my $exp = ($amount =~ m/[e]/) ? 1 : 0;
877
  # before the sprintf amount was a number, afterwards it's a string. because of the dynamic nature of perl
878
  # this is easy to confuse, so keep in mind: before this comment no s///, m//, concat or other strong ops on
879
  # $amount. after this comment no +,-,*,/,abs. it will only introduce subtle bugs.
881 880

  
882
  if (defined($places) && ($places ne '')) {
883
    if (not $exp) {
884
      if ($places < 0) {
885
        $amount *= 1;
886
        $places *= -1;
887

  
888
        if ($amount =~ /\.(\d+)/) {
889
          my $actual_places = length $1;
890
          $places = $actual_places if $actual_places > $places;
891
        }
892
      }
893
    }
894
    $amount = $self->round_amount($amount, $places);
895
  }
881
  $amount =~ s/0*$//;                                                    # cull trailing 0s
896 882

  
897 883
  my @d = map { s/\d//g; reverse split // } my $tmp = $myconfig->{numberformat}; # get delim chars
898
  my @p = split(/\./, $amount); # split amount at decimal point
899

  
900
  $p[0] =~ s/\B(?=(...)*$)/$d[1]/g if $d[1]; # add 1,000 delimiters
884
  my @p = split(/\./, $amount);                                          # split amount at decimal point
901 885

  
886
  $p[0] =~ s/\B(?=(...)*$)/$d[1]/g if $d[1];                             # add 1,000 delimiters
902 887
  $amount = $p[0];
903
  $amount .= $d[0].($p[1]||'').(0 x ($places - length ($p[1]||''))) if ($places || $p[1] ne '');
888
  if ($places || $p[1]) {
889
    $amount .= $d[0]
890
            .  ( $p[1] || '' )
891
            .  (0 x (abs($places || 0) - length ($p[1]||'')));           # pad the fraction
892
  }
904 893

  
905 894
  $amount = do {
906 895
    ($dash =~ /-/)    ? ($neg ? "($amount)"                            : "$amount" )                              :
......
908 897
                        ($neg ? "-$amount"                             : "$amount" )                              ;
909 898
  };
910 899

  
911

  
912 900
  $main::lxdebug->leave_sub(2);
913 901
  return $amount;
914 902
}
t/form/format_amount.t
25 25
is($::form->format_amount($config, 1000000000.1234, 2), '1,000,000,000.12', 'format 1000000000.1234 (numberformat: 1,000.00)');
26 26
is($::form->format_amount($config, -1000000000.1234, 2), '-1,000,000,000.12', 'format -1000000000.1234 (numberformat: 1,000.00)');
27 27

  
28
# negative places
29

  
30
is($::form->format_amount($config, 1.00045, -2), '1.00045', 'negative places');
31
is($::form->format_amount($config, 1.00045, -5), '1.00045', 'negative places 2');
32
is($::form->format_amount($config, 1, -2), '1.00', 'negative places 3');
33

  
34
# bugs amd edge cases
35

  
36
is($::form->format_amount({ numberformat => '1.000,00' }, 0.00005), '0,00005', 'messing with small numbers and no precision');
37
is($::form->format_amount({ numberformat => '1.000,00' }, undef), '0', 'undef');
38
is($::form->format_amount({ numberformat => '1.000,00' }, ''), '0', 'empty string');
39
is($::form->format_amount({ numberformat => '1.000,00' }, undef, 2), '0,00', 'undef with precision');
40
is($::form->format_amount({ numberformat => '1.000,00' }, '', 2), '0,00', 'empty string with prcesion');
41

  
42
is($::form->format_amount($config, 0.545, 0), '1', 'rounding up with precision 0');
43
is($::form->format_amount($config, -0.545, 0), '-1', 'neg rounding up with precision 0');
44

  
45
is($::form->format_amount($config, 1.00), '1', 'autotrim to 0 places');
46

  
47

  
48
# dash stuff
49

  
50
$config->{numberformat} = '1.000,00';
51

  
52
is($::form->format_amount($config, -350, 2, '-'), '(350,00)', 'dash -');
53

  
54

  
28 55
done_testing;
29 56

  
30 57
1;

Auch abrufbar als: Unified diff