File Coverage

blib/lib/Month/Simple.pm
Criterion Covered Total %
statement 24 61 39.3
branch 0 10 0.0
condition 0 12 0.0
subroutine 8 20 40.0
pod 7 8 87.5
total 39 111 35.1


line stmt bran cond sub pod time code
1             package Month::Simple;
2              
3 1     1   21657 use 5.010;
  1         6  
  1         52  
4 1     1   6 use strict;
  1         3  
  1         40  
5 1     1   5 use warnings;
  1         6  
  1         42  
6 1     1   889 use Date::Simple qw/ymd/;
  1         8467  
  1         54  
7 1     1   791 use Time::Local qw/timelocal/;
  1         1931  
  1         66  
8 1     1   6 use Carp qw/croak/;
  1         3  
  1         48  
9              
10 1     1   1064 use Data::Dumper;
  1         7777  
  1         181  
11              
12             our $VERSION = '0.03';
13              
14             use overload
15 0     0     q[""] => sub { my $d = shift->first_day; return substr "$d", 0, 7 },
  0            
16 0     0     '+' => sub { $_->[0]->delta($_[1]) },
17 0     0     '-' => sub { $_->[0]->delta(-$_[1]) },
18 0     0     cmp => sub { $_[0]->first_day cmp __PACKAGE__->new($_[1])->first_day },
19 1     1   8 ;
  1         2  
  1         15  
20              
21             sub new {
22 0     0 1   my ($class, $str) = @_;
23 0   0       $class = ref($class) || $class;
24 0 0 0       if (ref($str) && $str->isa('Date::Simple')) {
    0 0        
    0 0        
    0          
25 0           return bless { day => ymd($str->year, $str->month, 1) }, $class;
26             }
27             elsif ($str && $str =~ /^(\d{4})-?(\d{2})(?:-\d\d)?$/) {
28 0           return bless { day => ymd($1, $2, 1) }, $class;
29             }
30             elsif ($str && $str eq 'timestamp') {
31 0           my ($mon, $year) = (localtime $_[2])[4, 5];
32 0           return bless { day => ymd($year + 1900, $mon + 1, 1) }, $class;
33             }
34             elsif ($str) {
35 0           croak "Invalid month '$str' (valid: YYYY-MM, YYYYMM, YYYY-MM-DD)";
36             }
37             else {
38 0           my ($mon, $year) = (localtime $^T)[4, 5];
39 0           return bless { day => ymd($year + 1900, $mon + 1, 1) }, $class;
40             }
41             }
42              
43             sub first_day {
44 0     0 1   shift->{day};
45             }
46              
47             sub last_day {
48 0     0 0   shift->delta(1)->first_day - 1;
49             }
50              
51             sub delta {
52 0     0 1   my ($self, $delta) = @_;
53 0           $delta = int $delta;
54 0 0         return $self unless $delta;
55 0           my $d = $self->first_day;
56 0           while ($delta > 0) {
57             # there's no way we can advance more than one month
58             # when starting from the first of a month
59 0           $d += 31;
60 0           $d = ymd($d->year, $d->month, 1);
61             }
62             continue {
63 0           $delta--;
64             }
65 0           while ($delta < 0) {
66 0           $d--;
67 0           $d = ymd($d->year, $d->month, 1);
68             }
69             continue {
70 0           $delta++
71             }
72 0           return $self->new($d);
73             }
74              
75             sub first_second {
76 0     0 1   my $self = shift;
77 0           my $d = $self->first_day;
78 0           return timelocal(0, 0, 0, 1, $d->month - 1, $d->year - 1900);
79             }
80              
81             sub last_second {
82 0     0 1   my $self = shift;
83 0           $self->next->first_second - 1;
84             }
85              
86 0     0 1   sub prev { shift->delta(-1) };
87 0     0 1   sub next { shift->delta(1) };
88              
89             =head1 NAME
90              
91             Month::Simple - Simple month-based date arithmetics
92              
93             =head1 VERSION
94              
95             Version 0.03
96              
97             =head1 SYNOPSIS
98              
99             use Month::Simple;
100              
101             my $month = Month::Simple->new();
102             my $prev = $month->prev;
103             my $stamp = $prev->first_second;
104             my $in_yr = $month->delta(12);
105              
106             =head1 METHODS
107              
108             =head2 new
109              
110             Month::Simple->new(); # current month, using $^T as base
111             Month::Simple->new('2011-01');
112             Month::Simple->new('2011-01-02'); # day is ignored
113             Month::Simple->new(timestamp => time); # extract month from UNIX timestamp
114              
115             Creates a new C object. If no argument is provided, the current
116             month (based on the startup of the script, i.e. based on C<$^T>) is returned.
117              
118             The argument can be a date in format C, C, C
119             or a L object. Days are ignored.
120              
121             =head2 prev
122              
123             Returns a new C object for the month before the invocant month.
124              
125             =head2 next
126              
127             Returns a new C object for the month after the invocant month.
128              
129             =head2 delta(N)
130              
131             Returns a new C object. For positive C, it goes forward C
132             months, and backwards for negative C.
133              
134             =head2 first_second
135              
136             Returns a UNIX timestamp for the first second of the month.
137              
138             =head2 last_second
139              
140             Returns a UNIX timestamp for the last second of the month.
141              
142             =head2 first_day
143              
144             Returns a L object for the first day of the month.
145              
146             =head1 AUTHOR
147              
148             Moritz Lenz, C<< >> for the noris network AG.
149              
150             =head1 BUGS
151              
152             Please report any bugs or feature requests to C, or through
153             the web interface at L. I will be notified, and then you'll
154             automatically be notified of progress on your bug as I make changes.
155              
156              
157             =head1 SUPPORT
158              
159             You can find documentation for this module with the perldoc command.
160              
161             perldoc Month::Simple
162              
163              
164             You can also look for information at:
165              
166             =over 4
167              
168             =item * RT: CPAN's request tracker (report bugs here)
169              
170             L
171              
172             =item * AnnoCPAN: Annotated CPAN documentation
173              
174             L
175              
176             =item * CPAN Ratings
177              
178             L
179              
180             =item * Search CPAN
181              
182             L
183              
184             =back
185              
186             =head1 LICENSE AND COPYRIGHT
187              
188             Copyright 2013 Moritz Lenz.
189              
190             This program is free software; you can redistribute it and/or modify it
191             under the terms of either: the GNU General Public License as published
192             by the Free Software Foundation; or the Artistic License.
193              
194             See L for more information.
195              
196              
197             =cut
198              
199             1; # End of Month::Simple