File Coverage

blib/lib/Business/PL/PESEL.pm
Criterion Covered Total %
statement 51 61 83.6
branch 31 48 64.5
condition n/a
subroutine 9 9 100.0
pod 5 5 100.0
total 96 123 78.0


line stmt bran cond sub pod time code
1             # Copyright (C) 2012 by Tomasz Konojacki
2             #
3             # Permission is hereby granted, free of charge, to any person obtaining a copy
4             # of this software and associated documentation files (the "Software"), to deal
5             # in the Software without restriction, including without limitation the rights
6             # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7             # copies of the Software, and to permit persons to whom the Software is
8             # furnished to do so, subject to the following conditions:
9             #
10             # The above copyright notice and this permission notice shall be included in
11             # all copies or substantial portions of the Software.
12             #
13             # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14             # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15             # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16             # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17             # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18             # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19             # THE SOFTWARE.
20            
21             package Business::PL::PESEL;
22            
23             our $VERSION = '0.09';
24            
25 1     1   45133 use strict;
  1         2  
  1         40  
26 1     1   5 use warnings;
  1         2  
  1         28  
27 1     1   1890 use utf8;
  1         17  
  1         5  
28            
29 1     1   1208 use Time::Piece;
  1         26085  
  1         6  
30            
31             sub new {
32 3     3 1 391 my($class, %args) = @_;
33            
34 3 50       10 die 'PESEL number not specified in constructor' unless defined $args{-pesel};
35            
36 3         11 my $self = {
37             %args
38             };
39            
40 3         34 return bless $self, $class;
41             }
42            
43             sub is_valid {
44 15     15 1 25 my $self = shift;
45 15         31 my %args = @_;
46            
47 15         20 my($checksum, $month, $range);
48            
49 15 50       37 return 0 unless defined $self->{-pesel};
50            
51             # Calculate checksum
52 15 50       70 return 0 unless $self->{-pesel} =~ /^(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)$/;
53 15         93 $checksum = (1 * $1) + (3 * $2) + (7 * $3) + (9 * $4) + (1 * $5) + (3 * $6) + (7 * $7) + (9 * $8) + (1 * $9) + (3 * $10);
54 15         18 $checksum %= 10;
55 15 100       31 $checksum = 10 - $checksum unless $checksum == 0;
56 15 50       35 return 0 unless ($11 == $checksum);
57            
58 15 100       38 unless ($args{-dont_check_date}) {
59             # Check whether date is valid
60 7 100       9 eval {
61 7         16 $self->birth_date
62             } or return 0;
63             }
64            
65             # No errors, this is valid PESEL
66 11         137 return 1;
67             }
68            
69             sub is_male {
70 2     2 1 4 my $self = shift;
71            
72 2 50       8 die 'PESEL number not specified' unless defined $self->{-pesel};
73 2 100       4 die 'Invalid PESEL' unless $self->is_valid;
74 1 50       8 die 'Invalid PESEL' unless $self->{-pesel} =~ /^\d{9}(\d)\d$/;
75            
76 1 50       8 return 0 if $1 % 2 == 0;
77 0         0 return 1;
78             }
79            
80             sub is_female {
81 2     2 1 3 my $self = shift;
82            
83 2 50       7 die 'PESEL number not specified' unless defined $self->{-pesel};
84 2 100       5 die 'Invalid PESEL' unless $self->is_valid;
85 1 50       6 die 'Invalid PESEL' unless $self->{-pesel} =~ /^\d{9}(\d)\d$/;
86            
87 1 50       7 return 1 if $1 % 2 == 0;
88 0         0 return 0;
89             }
90            
91             sub birth_date {
92 8     8 1 11 my $self = shift;
93            
94 8         9 my($year, $month, $day, $tp, $date);
95            
96 8 50       24 die 'PESEL number not specified' unless defined $self->{-pesel};
97 8 50       27 die 'Invalid PESEL' unless $self->is_valid(-dont_check_date => 1) ;
98 8 50       60 die 'Invalid PESEL' unless ($year, $month, $day) = $self->{-pesel} =~ /^(\d{2})(\d{2})(\d{2})\d{5}$/;
99            
100 8 50       44 if ($month - 80 > 0) {
    50          
    50          
    50          
101 0         0 $month -= 80;
102 0         0 $year = 18 . $year;
103             }
104             elsif ($month - 60 > 0) {
105 0         0 $month -= 60;
106 0         0 $year = 22 . $year;
107             }
108             elsif ($month - 40 > 0) {
109 0         0 $month -= 40;
110 0         0 $year = 21 . $year;
111             }
112             elsif ($month - 20 > 0) {
113 0         0 $month -= 20;
114 0         0 $year = 20 . $year;
115             }
116             else {
117 8         15 $year = 19 . $year;
118             }
119            
120 8         18 $date = "$day-$month-$year";
121            
122 8 100       9 eval {
123 8         30 $tp = Time::Piece->strptime($date, '%d-%m-%Y');
124             } or die 'Invalid PESEL: invalid date!';
125            
126 5 100       553 die 'Invalid PESEL: invalid date!' if ($date ne $tp->strftime('%d-%m-%Y'));
127            
128 4         156 return $tp;
129             }
130            
131             1;
132            
133             __END__