File Coverage

blib/lib/DateTime/Format/PDF.pm
Criterion Covered Total %
statement 24 24 100.0
branch 6 6 100.0
condition 6 6 100.0
subroutine 6 6 100.0
pod 1 1 100.0
total 43 43 100.0


line stmt bran cond sub pod time code
1             package DateTime::Format::PDF;
2              
3 5     5   702048 use strict;
  5         14  
  5         184  
4 5     5   21 use warnings;
  5         8  
  5         2755  
5              
6             use DateTime::Format::Builder (
7             'parsers' => {
8             'parse_datetime' => [[
9             'preprocess' => sub {
10 15         520067 my %args = @_;
11 15         57 my ($date, $p) = @args{qw(input parsed)};
12 15 100       294 if ($date =~ s/(\d{2})'?(\d{2})'?$/$1$2/ms) {
    100          
13             } elsif ($date =~ s/Z$//ms) {
14 1         9 $p->{'time_zone'} = 'UTC';
15             }
16 15         81 return $date;
17             },
18 5         284 ], {
19             'length' => 6,
20             'regex' => qr{^D:(\d{4})$},
21             'params' => ['year'],
22             }, {
23             'length' => 8,
24             'regex' => qr{^D:(\d{4})(\d{2})$},
25             'params' => [qw(year month)],
26             }, {
27             'length' => 10,
28             'regex' => qr{^D:(\d{4})(\d{2})(\d{2})$},
29             'params' => [qw(year month day)],
30             }, {
31             'length' => 12,
32             'regex' => qr{^D:(\d{4})(\d{2})(\d{2})(\d{2})$},
33             'params' => [qw(year month day hour)],
34             }, {
35             'length' => 14,
36             'regex' => qr{^D:(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})$},
37             'params' => [qw(year month day hour minute)],
38             }, {
39             'length' => 16,
40             'regex' => qr{^D:(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$},
41             'params' => [qw(year month day hour minute second)],
42             }, {
43             'regex' => qr{^D:(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})([+\-]\d{4})$},
44             'params' => [qw(year month day hour minute second time_zone)],
45             }],
46             },
47 5     5   2945 );
  5         2913996  
48 5     5   14002 use Error::Pure qw(err);
  5         75600  
  5         174  
49 5     5   496 use Scalar::Util qw(blessed);
  5         10  
  5         877  
50              
51             our $VERSION = 0.02;
52              
53             sub format_datetime {
54 4     4 1 465306 my ($self, $dt) = @_;
55              
56 4 100 100     29 if (! defined $dt
      100        
57             || ! blessed($dt)
58             || ! $dt->isa('DateTime')) {
59              
60 3         41 err 'Bad DateTime object.',
61             'Value', $dt,
62             ;
63             }
64              
65 1         5 return $dt->strftime("D:%Y%m%d%H%M%S%z");
66             }
67              
68             1;
69              
70             __END__
71              
72             =pod
73              
74             =encoding utf8
75              
76             =head1 NAME
77              
78             DateTime::Format::PDF - PDF DateTime Parser and Formatter.
79              
80             =head1 SYNOPSIS
81              
82             use DateTime::Format::PDF;
83              
84             my $obj = DateTime::Format::PDF->new;
85             my $dt = $obj->parse_datetime($pdf_date);
86             my $pdf_date = $obj->format_datetime($dt);
87              
88             =head1 DESCRIPTION
89              
90             This module understands the formats used by PDF file. It can be used to parse these formats in order
91             to create L<DateTime> objects, and it can take a DateTime object and produce a string representing
92             it in a format accepted by PDF.
93              
94             =head1 METHODS
95              
96             =head2 C<new>
97              
98             my $obj = DateTime::Format::PDF->new(%params);
99              
100             Constructor.
101              
102             Returns instance of object.
103              
104             =head2 C<parse_datetime>
105              
106             my $dt = $obj->parse_datetime($pdf_date);
107              
108             Parse PDF datetime string.
109              
110             Possible valid strings:
111              
112             =over
113              
114             =item C<D:YYYY>
115              
116             =item C<D:YYYYMM>
117              
118             =item C<D:YYYYMMDD>
119              
120             =item C<D:YYYYMMDDHH>
121              
122             =item C<D:YYYYMMDDHHmm>
123              
124             =item C<D:YYYYMMDDHHmmSS>
125              
126             =item C<D:YYYYMMDDHHmmSSZ>
127              
128             =item C<D:YYYYMMDDHHmmSSOHHmm>
129              
130             =item C<D:YYYYMMDDHHmmSSOHH'mm>
131              
132             =item C<D:YYYYMMDDHHmmSSOHH'mm'>
133              
134             =item C<D:YYYYMMDDHHmmSSOHHmm'>
135              
136             =back
137              
138             Returns L<DateTime> object.
139              
140             =head2 C<format_datetime>
141              
142             my $pdf_date = $obj->format_datetime($dt);
143              
144             Format L<DateTime> object to PDF datetime string.
145             Output value is C<D:YYYYMMDDHHmmSSOHHmm>.
146              
147             Returns string.
148              
149             =head1 ERRORS
150              
151             format_datetime():
152             Bad DateTime object.
153             Value: %s
154              
155             parse_datetime():
156             Invalid date format: %s
157              
158             =head1 EXAMPLE1
159              
160             =for comment filename=parse_pdf_string.pl
161              
162             use strict;
163             use warnings;
164              
165             use DateTime::Format::PDF;
166              
167             # Object.
168             my $obj = DateTime::Format::PDF->new;
169              
170             # Parse date.
171             my $dt = $obj->parse_datetime("D:20240401084337-01'30");
172              
173             # Print out.
174             print $dt->strftime("%a, %d %b %Y %H:%M:%S %z")."\n";
175              
176             # Output like:
177             # Mon, 01 Apr 2024 08:43:37 -0130
178              
179             =head1 EXAMPLE2
180              
181             =for comment filename=format_pdf_string.pl
182              
183             use strict;
184             use warnings;
185              
186             use DateTime;
187             use DateTime::Format::PDF;
188              
189             # Object.
190             my $obj = DateTime::Format::PDF->new;
191              
192             # Example date.
193             my $dt = DateTime->now;
194              
195             # Format.
196             my $pdf_date = $obj->format_datetime($dt);
197              
198             # Print out.
199             print "PDF date: $pdf_date\n";
200              
201             # Output like:
202             # PDF date: D:20240401084337+0000
203              
204             =head1 EXAMPLE3
205              
206             =for comment filename=read_dates_from_pdf_builder.pl
207              
208             use strict;
209             use warnings;
210              
211             use DateTime::Format::PDF;
212             use PDF::Builder;
213              
214             if (@ARGV < 1) {
215             print STDERR "Usage: $0 pdf_file\n";
216             exit 1;
217             }
218             my $pdf_file = $ARGV[0];
219              
220             # Open file.
221             my $pdf = PDF::Builder->open($pdf_file);
222              
223             # Parser.
224             my $pdf_date_parser = DateTime::Format::PDF->new;
225              
226             my ($dt_created, $dt_modified);
227             my $print_format = "%a, %d %b %Y %H:%M:%S %z";
228             if (defined $pdf->created) {
229             $dt_created = $pdf_date_parser->parse_datetime($pdf->created);
230             print "Created: ".$dt_created->strftime($print_format)."\n";
231             }
232             if (defined $pdf->modified) {
233             $dt_modified = $pdf_date_parser->parse_datetime($pdf->modified);
234             print "Modified: ".$dt_modified->strftime($print_format)."\n";
235             }
236              
237             # Output:
238             # Created: Fri, 15 May 2009 08:40:48 +0200
239             # Modified: Fri, 15 May 2009 08:44:00 +0200
240              
241             =head1 EXAMPLE4
242              
243             =for comment filename=read_dates_from_pdf_api2.pl
244              
245             use strict;
246             use warnings;
247              
248             use DateTime::Format::PDF;
249             use PDF::API2;
250              
251             if (@ARGV < 1) {
252             print STDERR "Usage: $0 pdf_file\n";
253             exit 1;
254             }
255             my $pdf_file = $ARGV[0];
256              
257             # Open file.
258             my $pdf = PDF::API2->open($pdf_file);
259              
260             # Get meta info.
261             my %meta = $pdf->info;
262              
263             # Parser.
264             my $pdf_date_parser = DateTime::Format::PDF->new;
265              
266             my ($dt_created, $dt_modified);
267             my $print_format = "%a, %d %b %Y %H:%M:%S %z";
268             if (exists $meta{'CreationDate'}) {
269             $dt_created = $pdf_date_parser->parse_datetime($meta{'CreationDate'});
270             print "Created: ".$dt_created->strftime($print_format)."\n";
271             }
272             if (exists $meta{'ModDate'}) {
273             $dt_modified = $pdf_date_parser->parse_datetime($meta{'ModDate'});
274             print "Modified: ".$dt_modified->strftime($print_format)."\n";
275             }
276              
277             # Output:
278             # Created: Fri, 15 May 2009 08:40:48 +0200
279             # Modified: Fri, 15 May 2009 08:44:00 +0200
280              
281             =head1 DEPENDENCIES
282              
283             L<DateTime::Format::Builder>,
284             L<Error::Pure>,
285             L<Scalar::Util>.
286              
287             =head1 REPOSITORY
288              
289             L<https://github.com/michal-josef-spacek/DateTime-Format-PDF>
290              
291             =head1 AUTHOR
292              
293             Michal Josef Špaček L<mailto:skim@cpan.org>
294              
295             L<http://skim.cz>
296              
297             =head1 LICENSE AND COPYRIGHT
298              
299             © 2024 Michal Josef Špaček
300              
301             BSD 2-Clause License
302              
303             =head1 VERSION
304              
305             0.02
306              
307             =cut