File Coverage

blib/lib/Time/Duration/pl.pm
Criterion Covered Total %
statement 60 63 95.2
branch 19 22 86.3
condition 6 7 85.7
subroutine 19 22 86.3
pod 11 13 84.6
total 115 127 90.5


line stmt bran cond sub pod time code
1             package Time::Duration::pl;
2             # ABSTRACT: Describe time duration in Polish
3              
4 3     3   42119 use 5.8.0;
  3         14  
  3         148  
5 3     3   1991 use utf8;
  3         25  
  3         18  
6 3     3   100 use strict;
  3         7  
  3         111  
7 3     3   16 use warnings;
  3         7  
  3         185  
8              
9             our $VERSION = '0.002'; # VERSION: generated by DZP::OurPkgVersion
10              
11 3     3   18 use base qw(Exporter);
  3         6  
  3         503  
12              
13             our @EXPORT = qw(
14             later later_exact
15             earlier earlier_exact
16             ago ago_exact
17             from_now from_now_exact
18             duration duration_exact
19             concise
20             );
21             our @EXPORT_OK = ( 'interval', @EXPORT );
22              
23 3     3   3093 use Time::Duration qw();
  3         6061  
  3         2964  
24              
25             my %en2pl = (
26             # singular plural plural in genitive
27             second => [ 'sekunda', 'sekundy', 'sekund' ],
28             minute => [ 'minuta', 'minuty', 'minut' ],
29             hour => [ 'godzina', 'godziny', 'godzin' ],
30             day => [ 'dzień', 'dni', 'dni' ],
31             year => [ 'rok', 'lata', 'lat' ],
32             );
33              
34             my %short = map { $_ => substr($_, 0, 1) } map { @{$_} } values %en2pl;
35             my $comp_re = join '|', map { @{$_} } values %en2pl;
36              
37             sub concise ($) {
38 29     29 1 49 my ( $string ) = @_;
39              
40 29         53 for ($string) {
41 29         72 tr/,//d;
42 29         122 s/\bi\b//;
43 29         482 s/\b($comp_re)\b/$short{$1}/g;
44 29         256 s/\s*(\d+)\s*/$1/g;
45              
46             # restore prefixed intervals
47 29         109 s/za/za /;
48             }
49              
50 29         200 return $string;
51             }
52              
53             sub later {
54 124     124 1 857 interval( $_[0], $_[1], '%s wcześniej', '%s później', 'teraz');
55             }
56              
57             sub later_exact {
58 59     59 1 164 interval_exact($_[0], $_[1], '%s wcześniej', '%s później', 'teraz');
59             }
60              
61             sub earlier {
62 6     6 1 22 interval( $_[0], $_[1], '%s później', '%s wcześniej', 'teraz');
63             }
64              
65             sub earlier_exact {
66 0     0 1 0 interval_exact($_[0], $_[1], '%s później', '%s wcześniej', 'teraz');
67             }
68              
69             sub ago {
70 6     6 1 22 interval( $_[0], $_[1], 'za %s', '%s temu', 'teraz');
71             }
72              
73             sub ago_exact {
74 0     0 1 0 interval_exact($_[0], $_[1], 'za %s', '%s temu', 'teraz');
75             }
76              
77             sub from_now {
78 6     6 1 21 interval( $_[0], $_[1], '%s temu', 'za %s', 'teraz');
79             }
80              
81             sub from_now_exact {
82 0     0 1 0 interval_exact($_[0], $_[1], '%s temu', 'za %s', 'teraz');
83             }
84              
85             sub duration_exact {
86 4     4 1 6 my ( $span ) = @_; # interval in seconds
87 4 50       10 return '0 sekund' unless $span;
88 4         14 _render(
89             '%s',
90             Time::Duration::_separate(abs $span));
91             }
92              
93             sub duration {
94 18     18 1 151 my ( $span, $precision ) = @_; # interval in seconds
95 18 100       47 return '0 sekund' unless $span;
96 16   100     130 _render(
97             '%s',
98             Time::Duration::_approximate(
99             int($precision || 0) || 2, # precision (default: 2)
100             Time::Duration::_separate(abs $span)));
101             }
102              
103             sub interval_exact {
104 59     59 0 76 my ( $span ) = @_; # interval in seconds
105 59 100       151 my $direction = ($span <= -1) ? $_[2] # what a neg number gets
    50          
106             : ($span >= 1) ? $_[3] # what a pos number gets
107             : return $_[4]; # what zero gets
108 58         145 _render($direction, Time::Duration::_separate($span));
109             }
110              
111             sub interval {
112 142     142 0 275 my ( $span, $precision ) = @_; # interval in seconds
113 142 100       392 my $direction = ($span <= -1) ? $_[2] # what a neg number gets
    100          
114             : ($span >= 1) ? $_[3] # what a pos number gets
115             : return $_[4]; # what zero gets
116 132   100     882 _render(
117             $direction,
118             Time::Duration::_approximate(
119             int($precision || 0) || 2, # precision (default: 2)
120             Time::Duration::_separate($span)));
121             }
122              
123             BEGIN {
124             # generally numbers' units in Polish use plural form in genitive case,
125             # but for some values like 2, 3, 4, 22, 23, 24, 32, 33, 34, etc. nominative
126             # is used
127 3     3   802 my %case_index = (
128             0 => 2,
129             1 => 2,
130             2 => 1,
131             3 => 1,
132             4 => 1,
133             5 => 2,
134             6 => 2,
135             7 => 2,
136             8 => 2,
137             9 => 2,
138             10 => 2,
139             11 => 2,
140             12 => 2,
141             13 => 2,
142             14 => 2,
143             );
144              
145             sub _determine_case {
146 348     348   454 my ( $amount ) = @_;
147 348 100       898 return 0 if $amount == 1; # use singular for 1
148 248   66     1423 return $case_index{$amount} # choose case explicitely for 2..14
149             || $case_index{$amount % 10}; # or use last digit for greater values
150             }
151             }
152              
153             sub _render {
154             # Make it into Polish
155 210     210   7960 my $direction = shift;
156 1050         1529 my @wheel = map {
157 210         328 my ( $unit, $amount ) = @{$_};
  1050         1029  
158 1050 100       2529 ( $amount == 0 )
159             ? ()
160             : $amount . ' ' . $en2pl{$unit}[_determine_case($amount)]
161             } @_;
162              
163 210 50       449 return 'teraz' unless @wheel; # sanity
164              
165 210         241 my $result;
166 210 100       415 if (@wheel == 1) {
    100          
167 132         173 $result = $wheel[0];
168             }
169             elsif (@wheel == 2) {
170 36         97 $result = $wheel[0] . ' i ' . $wheel[1];
171             }
172             else {
173 42         59 my $last = pop @wheel;
174 42         134 $result = join(', ', @wheel) . ' i ' . $last;
175             }
176              
177 210         1456 return sprintf($direction, $result);
178             }
179              
180             1;
181              
182             __END__