File Coverage

blib/lib/File/Find/IncludesTimeRange.pm
Criterion Covered Total %
statement 14 73 19.1
branch 0 34 0.0
condition 0 21 0.0
subroutine 5 6 83.3
pod 1 1 100.0
total 20 135 14.8


line stmt bran cond sub pod time code
1             package File::Find::IncludesTimeRange;
2              
3 1     1   67497 use 5.006;
  1         4  
4 1     1   6 use strict;
  1         3  
  1         39  
5 1     1   5 use warnings;
  1         2  
  1         27  
6 1     1   580 use Time::Piece;
  1         12416  
  1         5  
7              
8             =head1 NAME
9              
10             File::Find::IncludesTimeRange - Takes a array of time stamped items(largely meant for use with files) returns ones that include the specified time range.
11              
12             =head1 VERSION
13              
14             Version 0.0.1
15              
16             =cut
17              
18             our $VERSION = '0.0.1';
19              
20             =head1 SYNOPSIS
21              
22             use File::Find::IncludesTimeRange;
23             usexs Time::Piece;
24             use Data::Dumper;
25              
26             my @files=(
27             'daemonlogger.1677468390.pcap',
28             'daemonlogger.1677468511.pcap',
29             'daemonlogger.1677468632.pcap',
30             'daemonlogger.1677468753.pcap',
31             'daemonlogger.1677468874.pcap',
32             'daemonlogger.1677468995.pcap',
33             'daemonlogger.1677469116.pcap',
34             'daemonlogger.1677469237.pcap',
35             'daemonlogger.1677469358.pcap',
36             'daemonlogger.1677469479.pcap',
37             'daemonlogger.1677469600.pcap',
38             'daemonlogger.1677469721.pcap',
39             );
40              
41             print Dumper(\@files);
42              
43             my $start=Time::Piece->strptime('1677468620', '%s');
44             my $end=Time::Piece->strptime( '1677468633', '%s');
45              
46             my $found=File::Find::IncludesTimeRange->find(
47             items=>\@files,
48             start=>$start,
49             end=>$end,
50             regex=>'(?\d\d\d\d\d\d+)(\.pcap|(?\.\d+)\.pcap)$',
51             strptime=>'%s',
52             );
53              
54             print Dumper($found);
55              
56             =head1 SUBROUTINES
57              
58             =head2 find
59              
60             Searches through a list of items , finds the ones that appear to be timestamped.
61             It will then sort the found time stamps and return the ones that include the
62             specified time periods.
63              
64             There following options are taken.
65              
66             - items :: A array ref of items to examine.
67              
68             - start :: A Time::Piece object set to the start time.
69              
70             - end :: A Time::Piece object set to the end time.
71              
72             - regex :: A regex to use for matching the files. Requires uses of the named
73             group 'timestamp' for capturing the timestamp. If it includes micro
74             seconds in it, since Time::Piece->strptime does not handle those,
75             those can be captured via the group 'subsec'. They will then be
76             appended to to the epoch time of any parsed timestamp for sorting
77             purposes.
78             - Default :: (?\d\d\d\d\d\d+)(\.pcap|(?\.\d+)\.pcap)$
79              
80             - strptime :: The format for use with L->strptime.
81             - Default :: %s
82              
83             =cut
84              
85             sub find {
86 0     0 1   my ( $blank, %opts ) = @_;
87              
88             # some basic error checking
89 0 0         if ( !defined( $opts{start} ) ) {
    0          
    0          
    0          
    0          
    0          
    0          
90 0           die('$opts{start} is undef');
91             }
92             elsif ( !defined( $opts{end} ) ) {
93 0           die('$opts{end} is undef');
94             }
95             elsif ( !defined( $opts{items} ) ) {
96 0           die('$opts{items} is undef');
97             }
98             elsif ( ref( $opts{start} ) ne 'Time::Piece' ) {
99 0           die('$opts{start} is not a Time::Piece object');
100             }
101             elsif ( ref( $opts{end} ) ne 'Time::Piece' ) {
102 0           die('$opts{end} is not a Time::Piece object');
103             }
104             elsif ( ref( $opts{items} ) ne 'ARRAY' ) {
105 0           die('$opts{items} is not a ARRAY');
106             }elsif ( $opts{start} > $opts{end} ) {
107 0           die('$opts{start} is greater than $opts{end}');
108             }
109              
110 0 0         if (!defined($opts{strptime}) ) {
111 0           $opts{strptime}='%s';
112             }
113              
114 0 0         if (!defined($opts{regex})) {
115 0           $opts{regex}='(?\d\d\d\d\d\d+)(\.pcap|(?\.\d+)\.pcap)$';
116             }
117              
118 0           my $start = $opts{start}->epoch;
119 0           my $end = $opts{end}->epoch;
120              
121 0           my $found = {};
122 0           my $timestamp_save = {};
123 0           foreach my $item ( @{ $opts{items} } ) {
  0            
124 0 0         if ( $item =~ /$opts{regex}/ ) {
125 0           my $subsec = '';
126 1     1   802 my $timestamp_raw = $+{timestamp};
  1         446  
  1         395  
  0            
127 0 0         if ( defined( $+{subsec} ) ) {
128 0           $subsec = $+{subsec};
129             }
130              
131 0           my $timestamp;
132 0           eval { $timestamp = Time::Piece->strptime( $timestamp_raw, $opts{strptime} ); };
  0            
133 0 0 0       if ( !$@ && defined($timestamp) ) {
134 0           my $full_timestamp = $timestamp->epoch . $subsec;
135 0 0         if ( !defined( $found->{$full_timestamp} ) ) {
136 0           $found->{$full_timestamp} = [];
137 0           $timestamp_save->{$full_timestamp} = $timestamp;
138             }
139 0           push( @{ $found->{$full_timestamp} }, $item );
  0            
140             }
141             }
142             }
143              
144 0           my @found_timestamps = sort( keys( %{$found} ) );
  0            
145 0           my $previous_timestamp;
146             my $previous_found;
147 0           my $previous_t;
148 0           my @timestamp_to_return;
149 0           foreach my $current_timestamp (@found_timestamps) {
150 0           my $t = $timestamp_save->{$current_timestamp};
151              
152 0 0 0       if ( ( $opts{start} <= $t ) && ( $t <= $opts{end} ) ) {
153 0           push( @timestamp_to_return, $current_timestamp );
154              
155             # if we find one that it is between, but not equal, then add the previous as that contains the start
156 0 0 0       if ( defined($previous_timestamp) && !$previous_found && ( $opts{start} != $t ) ) {
    0 0        
      0        
157 0           $previous_found = 1;
158 0           push( @timestamp_to_return, $previous_timestamp );
159             }elsif (!$previous_found && ( $opts{start} == $t ) ) {
160 0           $previous_found = 1;
161             }
162             }
163              
164             # if the time period falls between when two files was created, we will find
165 0 0 0       if (!$previous_found && defined($previous_timestamp) && ( $opts{end} < $t )) {
      0        
166 0           $previous_found=1;
167 0           push( @timestamp_to_return, $previous_timestamp );
168             }
169              
170 0           $previous_timestamp = $current_timestamp;
171 0           $previous_t = $t;
172             }
173              
174 0           my $to_return=[];
175             # the second sort is needed as if
176 0           foreach my $item (sort(@timestamp_to_return)) {
177 0           foreach my $file (@{ $found->{$item} }) {
  0            
178 0           push(@{ $to_return }, $file);
  0            
179             }
180             }
181              
182 0           return $to_return;
183             }
184              
185             =head1 AUTHOR
186              
187             Zane C. Bower-Hadley, C<< >>
188              
189             =head1 BUGS
190              
191             Please report any bugs or feature requests to C, or through
192             the web interface at L. I will be notified, and then you'll
193             automatically be notified of progress on your bug as I make changes.
194              
195              
196              
197              
198             =head1 SUPPORT
199              
200             You can find documentation for this module with the perldoc command.
201              
202             perldoc File::Find::IncludesTimeRange
203              
204              
205             You can also look for information at:
206              
207             =over 4
208              
209             =item * RT: CPAN's request tracker (report bugs here)
210              
211             L
212              
213             =item * CPAN Ratings
214              
215             L
216              
217             =item * Search CPAN
218              
219             L
220              
221             =back
222              
223              
224             =head1 ACKNOWLEDGEMENTS
225              
226              
227             =head1 LICENSE AND COPYRIGHT
228              
229             This software is Copyright (c) 2023 by Zane C. Bower-Hadley.
230              
231             This is free software, licensed under:
232              
233             The Artistic License 2.0 (GPL Compatible)
234              
235              
236             =cut
237              
238             1; # End of File::Find::IncludesTimeRange