File Coverage

blib/lib/Date/Extract/P800Picture.pm
Criterion Covered Total %
statement 48 48 100.0
branch 6 6 100.0
condition n/a
subroutine 12 12 100.0
pod 1 1 100.0
total 67 67 100.0


line stmt bran cond sub pod time code
1             # -*- cperl; cperl-indent-level: 4 -*-
2             # Copyright (C) 2008-2020, Roland van Ipenburg
3             package Date::Extract::P800Picture v1.1.4;
4              
5 8     8   1421226 use strict;
  8         82  
  8         246  
6 8     8   54 use warnings;
  8         21  
  8         219  
7              
8 8     8   45 use utf8;
  8         17  
  8         86  
9 8     8   355 use 5.014000;
  8         30  
10              
11 8     8   4741 use Moose;
  8         3821233  
  8         57  
12              
13 8     8   61802 use POSIX ();
  8         21  
  8         242  
14 8     8   5773 use English qw( -no_match_vars);
  8         30615  
  8         57  
15 8     8   9925 use DateTime ();
  8         3430930  
  8         390  
16              
17 8     8   4544 use Date::Extract::P800Picture::Exceptions ();
  8         26  
  8         184  
18              
19 8     8   4384 use Readonly ();
  8         32537  
  8         4457  
20             ## no critic (ProhibitCallsToUnexportedSubs)
21             Readonly::Scalar my $EPOCH_YEAR => 2000;
22             Readonly::Scalar my $MONTHS_IN_YEAR => 12;
23             Readonly::Scalar my $MAX_DAYS_IN_MONTH => 31;
24             Readonly::Scalar my $HOURS_IN_DAY => 24;
25             Readonly::Scalar my $BASE_N => 36;
26             Readonly::Scalar my $TZ => 'UTC';
27             Readonly::Hash my %ERR => (
28             'MISSING_DATE' => q{No date found in filename '%s'},
29             'MISSING_FILENAME' => q{Filename is not set, nothing to extract},
30             );
31             ## use critic
32              
33             ## no critic (ProhibitComplexRegexes)
34             my $PATTERN = qr{
35             ^
36             (?<year> [[:alnum:]] ) # max 36 years: $EPOCH_YEAR 2000 to 2035
37             (?<month> [[:digit:]AB] ) # max 12 months
38             (?<day> [[:digit:]A-U]) # max 31 days
39             (?<hour> [[:digit:]A-N]) # max 24 hours: 0 to 23
40             (?<serial> [[:digit:]]{4}) # max unique up to 10000 pictures per hour
41             (?<suffix> [.]JPG ) # JPEG extension
42             $
43             }aixsm;
44             ## use critic
45              
46             ## no critic qw(ProhibitCallsToUndeclaredSubs)
47             has 'filename' => (
48             ## use critic
49             'is' => 'rw',
50             'isa' => 'Str',
51             );
52              
53             ## no critic qw(ProhibitCallsToUndeclaredSubs)
54             has 'datetime' => (
55             ## use critic
56             'is' => 'rw',
57             'isa' => 'DateTime',
58             'default' => sub {
59             DateTime->new(
60             'year' => $EPOCH_YEAR,
61             'time_zone' => $TZ,
62             );
63             },
64             );
65              
66             sub extract {
67 2454     2454 1 1740962 my ( $self, $filename ) = @_;
68 2454 100       96843 ( defined $filename ) && $self->filename($filename);
69 2454 100       72711 if ( defined $self->filename ) {
70 2453         69776 $self->filename =~ $PATTERN;
71             my ( $year, $month, $day, $hour ) = (
72             $LAST_PAREN_MATCH{'year'}, $LAST_PAREN_MATCH{'month'},
73 2453         28713 $LAST_PAREN_MATCH{'day'}, $LAST_PAREN_MATCH{'hour'},
74             );
75              
76 2453 100       9532 if ( defined $year ) {
77 2449         7099 $self->_parse( \$year, $BASE_N );
78 2449         6970 $self->_parse( \$month, $MONTHS_IN_YEAR );
79 2449         6213 $self->_parse( \$day, $MAX_DAYS_IN_MONTH );
80 2449         5988 $self->_parse( \$hour, $HOURS_IN_DAY );
81 2449         75695 $self->datetime->set(
82             'year' => $year + $EPOCH_YEAR,
83             'month' => $month + 1,
84             'day' => $day + 1,
85             'hour' => $hour,
86             );
87             }
88             else {
89             ## no critic (RequireExplicitInclusion)
90             DateExtractP800PictureException->throw(
91             ## use critic
92 4         124 'error' => sprintf $ERR{'MISSING_DATE'},
93             $self->filename,
94             );
95             }
96             }
97             else {
98             ## no critic (RequireExplicitInclusion)
99             DateExtractP800PictureException->throw(
100             ## use critic
101 1         21 'error' => $ERR{'MISSING_FILENAME'},
102             );
103             }
104 2442         1265463 return $self->datetime;
105             }
106              
107             # Converts a character to a number given base. Changes the referenced part.
108              
109             sub _parse {
110 9796     9796   16317 my ( $self, $sr_part, $base ) = @_;
111 9796         13561 my $n_unparsed = 0;
112              
113             ## no critic (ProhibitCallsToUnexportedSubs)
114 9796         13422 return ( ${$sr_part}, $n_unparsed ) = POSIX::strtol( ${$sr_part}, $base );
  9796         17683  
  9796         21258  
115             ## use critic
116             }
117              
118             1;
119              
120             __END__
121              
122             =encoding utf8
123              
124             =for stopwords Ericsson Filename MERCHANTABILITY POSIX filename timestamp jpg JPG
125             YMDH DateTime undef perl Readonly perls Ipenburg
126              
127             =head1 NAME
128              
129             Date::Extract::P800Picture - extract the date from Sony Ericsson P800 pictures
130              
131             =head1 VERSION
132              
133             This document describes Date::Extract::P800Picture version v1.1.4.
134              
135             =head1 SYNOPSIS
136              
137             use Date::Extract::P800Picture;
138              
139             $filename = "8B360001.JPG"; # 2008-12-04T6:00:00
140              
141             $parser = new Date::Extract::P800Picture();
142             $parser = new Date::Extract::P800Picture('filename' => $filename);
143              
144             $datetime = $parser->extract();
145             $datetime = $parser->extract($filename);
146              
147             =head1 DESCRIPTION
148              
149             The Sony Ericsson P800 camera phone stores pictures taken with the camera on
150             the device with a filename consisting of the date and the hour the picture was
151             taken, followed by a four digit number and the .JPG extension. The format of
152             the date and the hour is YMDH, in which the single characters are base 36 to
153             fit a range of about 36 years, 12 months, 31 days and 24 hours since the year
154             2000 in a case insensitive US-ASCII representation.
155              
156             =head1 SUBROUTINES/METHODS
157              
158             =over 4
159              
160             =item Date::Extract::P800Picture-E<gt>new()
161              
162             =item Date::Extract::P800Picture-E<gt>new('filename' => $filename)
163              
164             Constructs a new Date::Extract::P800Picture object.
165              
166             =item $parser->filename($filename);
167              
168             Sets the filename to extract the date and hour from.
169              
170             =item $obj-E<gt>extract()
171              
172             Extract date and hour from the string and returns it as L<DateTime|DateTime>
173             object. Returns undef if no valid date could be extracted.
174              
175             =back
176              
177             =head1 CONFIGURATION AND ENVIRONMENT
178              
179             No configuration and environment settings are used.
180              
181             =head1 DEPENDENCIES
182              
183             =over 4
184              
185             =item * perl 5.14
186              
187             =item * L<POSIX|POSIX>
188              
189             =item * L<English|English>
190              
191             =item * L<DateTime|DateTime>
192              
193             =item * L<Readonly|Readonly>
194              
195             =item * L<Moose|Moose>
196              
197             =item * L<Test::More|Test::More>
198              
199             =back
200              
201             =head1 INCOMPATIBILITIES
202              
203             =over 4
204              
205             =item * To avoid ambiguity between more common date notations and the
206             Sony Ericsson P800's date notation this is a separate module. It's highly
207             unlikely that in any other setting "2000" means the first of January 2002.
208              
209             =item * For perls earlier than 5.14 version 0.04 of this module provides the
210             same functionality in a perl 5.6 compatible way.
211              
212             =back
213              
214             =head1 DIAGNOSTICS
215              
216             An exception in the form of an L<Exception::Class|Exception::Class> named
217             C<DateExtractP800PictureException> is thrown when a date can't be extracted
218             from the string:
219              
220             =over 4
221              
222             =item * No date found in filename '%s'
223              
224             =item * Filename is not set, nothing to extract
225              
226             =back
227              
228             =head1 BUGS AND LIMITATIONS
229              
230             =over 4
231              
232             =item * Usually the files are transferred from the P800 to other systems in a
233             way that hasn't completely preserved the timestamp of the file, so there is no
234             reliable way to double check the results by comparing the date extracted from
235             the filename with the timestamp of the file.
236              
237             =item * There are no error values to provide different exit statuses for
238             different failure reasons
239              
240             =back
241              
242             Please report any bugs or feature requests at
243             L<RT for rt.cpan.org|
244             https://rt.cpan.org/Dist/Display.html?Queue=Date-Extract-P800Picture>.
245              
246             =head1 AUTHOR
247              
248             Roland van Ipenburg, E<lt>roland@rolandvanipenburg.comE<gt>
249              
250             =head1 LICENSE AND COPYRIGHT
251              
252             Copyright (C) 2008-2020, Roland van Ipenburg
253              
254             This library is free software; you can redistribute it and/or modify
255             it under the same terms as Perl itself, either Perl version 5.14.0 or,
256             at your option, any later version of Perl 5 you may have available.
257              
258             =head1 DISCLAIMER OF WARRANTY
259              
260             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
264             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
265             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
266             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
267             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
268             NECESSARY SERVICING, REPAIR, OR CORRECTION.
269              
270             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
273             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
274             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
275             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
276             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
277             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
278             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
279             SUCH DAMAGES.
280              
281             =cut