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   197816 use strict;
  3         4  
  3         74  
5 3     3   8 use warnings;
  3         3  
  3         65  
6              
7 3     3   1300 use version; our $VERSION = qv('v1.2.0');
  3         4215  
  3         12  
8              
9 3     3   983 use DateTime qw( );
  3         75675  
  3         57  
10 3     3   14 use DateTime::TimeZone qw( );
  3         3  
  3         38  
11 3     3   9 use Exporter qw( import );
  3         3  
  3         73  
12 3     3   10 use Scalar::Util qw( );
  3         3  
  3         967  
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   2152 my ($trunc, $dt, $tz) = @_;
27              
28 43 100       224 if (Scalar::Util::blessed($dt)) {
29 16   66     64 $tz ||= $dt->time_zone;
30 16 100       100 $dt = $dt->clone->set_time_zone('floating')->truncate( to => $trunc )
31             if $trunc;
32             } else {
33 27   100     94 $tz ||= 'local';
34 27   100     263 $dt = DateTime->new( year => $dt->[0], month => $dt->[1] || 1, day => $dt->[2] || 1 );
      100        
35             }
36              
37 43 100       7585 $tz = DateTime::TimeZone->new( name => $tz )
38             if !ref($tz);
39              
40 43         17122 my $target_day = ( $dt->local_rd_values )[0];
41 43         279 my $min_epoch = int($dt->epoch()/60) - 24*60;
42 43         373 my $max_epoch = int($dt->epoch()/60) + 24*60;
43 43         250 while ($max_epoch - $min_epoch > 1) {
44 510         668 my $epoch = ( $min_epoch + $max_epoch ) >> 1;
45 510 100       1438 if (( DateTime->from_epoch( epoch => $epoch*60, time_zone => $tz )->local_rd_values )[0] < $target_day) {
46 332         93959 $min_epoch = $epoch;
47             } else {
48 178         60732 $max_epoch = $epoch;
49             }
50             }
51              
52 43         158 return DateTime->from_epoch(epoch => $max_epoch*60, time_zone => $tz);
53             }
54              
55 19     19 1 49483 sub start_of_date { _start_of_date(undef, @_) }
56 12     12 1 25183 sub start_of_month { _start_of_date('month', @_) }
57 8     8 1 10699 sub start_of_year { _start_of_date('year', @_) }
58 4   100 4 1 6197 sub start_of_today { _start_of_date(undef, DateTime->now( time_zone => $_[0] || 'local' )) }
59              
60             {
61 3     3   14 no warnings qw( once );
  3         4  
  3         287  
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__