File Coverage

blib/lib/DateTimeX/Start.pm
Criterion Covered Total %
statement 44 44 100.0
branch 8 8 100.0
condition 10 11 90.9
subroutine 13 13 100.0
pod 4 4 100.0
total 79 80 98.7


line stmt bran cond sub pod time code
1              
2             package DateTimeX::Start;
3              
4 3     3   181062 use strict;
  3         4  
  3         69  
5 3     3   10 use warnings;
  3         3  
  3         58  
6              
7 3     3   1115 use version; our $VERSION = qv('v1.0.0');
  3         3827  
  3         13  
8              
9 3     3   946 use DateTime qw( );
  3         71857  
  3         54  
10 3     3   12 use DateTime::TimeZone qw( );
  3         3  
  3         40  
11 3     3   9 use Exporter qw( import );
  3         2  
  3         64  
12 3     3   9 use Scalar::Util qw( );
  3         3  
  3         884  
13              
14              
15             my @long = qw( start_of_date start_of_month start_of_year start_of_today );
16             my @short = qw( date month year today );
17             our @EXPORT_OK = ( @long, @short );
18             our %EXPORT_TAGS = (
19             'ALL' => \@EXPORT_OK,
20             'long' => \@long,
21             'short' => \@short,
22             );
23              
24              
25             sub _start_of_date {
26 43     43   1400 my ($trunc, $dt, $tz) = @_;
27              
28 43 100       121 if (Scalar::Util::blessed($dt)) {
29 16   66     39 $tz ||= $dt->time_zone;
30 16 100       64 $dt = $dt->clone->set_time_zone('floating')->truncate( to => $trunc )
31             if $trunc;
32             } else {
33 27   100     56 $tz ||= 'local';
34 27   100     158 $dt = DateTime->new( year => $dt->[0], month => $dt->[1] || 1, day => $dt->[2] || 1 );
      100        
35             }
36              
37 43 100       5295 $tz = DateTime::TimeZone->new( name => $tz )
38             if !ref($tz);
39              
40 43         16168 my $target_day = ( $dt->local_rd_values )[0];
41 43         194 my $min_epoch = int($dt->epoch()/60) - 24*60;
42 43         253 my $max_epoch = int($dt->epoch()/60) + 24*60;
43 43         184 while ($max_epoch - $min_epoch > 1) {
44 514         494 my $epoch = ( $min_epoch + $max_epoch ) >> 1;
45 514 100       1021 if (( DateTime->from_epoch( epoch => $epoch*60, time_zone => $tz )->local_rd_values )[0] < $target_day) {
46 338         68306 $min_epoch = $epoch;
47             } else {
48 176         43106 $max_epoch = $epoch;
49             }
50             }
51              
52 43         96 return DateTime->from_epoch(epoch => $max_epoch*60, time_zone => $tz);
53             }
54              
55 19     19 1 28297 sub start_of_date { _start_of_date(undef, @_) }
56 12     12 1 9826 sub start_of_month { _start_of_date('month', @_) }
57 8     8 1 6940 sub start_of_year { _start_of_date('year', @_) }
58 4   100 4 1 3783 sub start_of_today { _start_of_date(undef, DateTime->now( time_zone => $_[0] || 'local' )) }
59              
60             {
61 3     3   12 no warnings qw( once );
  3         2  
  3         239  
62             *date = \&start_of_date;
63             *month = \&start_of_month;
64             *year = \&start_of_year;
65             *today = \&start_of_today;
66             }
67              
68              
69             1;
70              
71             __END__