File Coverage

blib/lib/Month/Simple.pm
Criterion Covered Total %
statement 23 62 37.1
branch 0 10 0.0
condition 0 12 0.0
subroutine 8 22 36.3
pod 10 10 100.0
total 41 116 35.3


line stmt bran cond sub pod time code
1             package Month::Simple;
2              
3 1     1   125501 use 5.010;
  1         5  
4 1     1   6 use strict;
  1         2  
  1         45  
5 1     1   5 use warnings;
  1         11  
  1         67  
6 1     1   797 use Date::Simple qw/ymd/;
  1         10039  
  1         86  
7 1     1   675 use Time::Local qw/timelocal/;
  1         3425  
  1         111  
8 1     1   10 use Carp qw/croak/;
  1         2  
  1         61  
9              
10 1     1   754 use Data::Dumper;
  1         11660  
  1         238  
11              
12             our $VERSION = '0.05';
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   10 ;
  1         6  
  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 1   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 month { shift->{day}->month }
87 0     0 1   sub year { shift->{day}->year }
88              
89 0     0 1   sub prev { shift->delta(-1) };
90 0     0 1   sub next { shift->delta(1) };
91              
92             =head1 NAME
93              
94             Month::Simple - Simple month-based date arithmetics
95              
96             =head1 VERSION
97              
98             Version 0.05
99              
100             =head1 SYNOPSIS
101              
102             use Month::Simple;
103              
104             my $month = Month::Simple->new();
105             my $prev = $month->prev;
106             my $stamp = $prev->first_second;
107             my $in_yr = $month->delta(12);
108              
109             =head1 METHODS
110              
111             =head2 new
112              
113             Month::Simple->new(); # current month, using $^T as base
114             Month::Simple->new('2011-01');
115             Month::Simple->new('2011-01-02'); # day is ignored
116             Month::Simple->new(timestamp => time); # extract month from UNIX timestamp
117              
118             Creates a new C object. If no argument is provided, the current
119             month (based on the startup of the script, i.e. based on C<$^T>) is returned.
120              
121             The argument can be a date in format C, C, C
122             or a L object. Days are ignored.
123              
124             =head2 prev
125              
126             Returns a new C object for the month before the invocant month.
127              
128             =head2 next
129              
130             Returns a new C object for the month after the invocant month.
131              
132             =head2 delta(N)
133              
134             Returns a new C object. For positive C, it goes forward C
135             months, and backwards for negative C.
136              
137             =head2 first_second
138              
139             Returns a UNIX timestamp for the first second of the month.
140              
141             =head2 last_second
142              
143             Returns a UNIX timestamp for the last second of the month.
144              
145             =head2 month
146              
147             Returns the month as an integer between 1 and 12.
148              
149             say Month::Simple->new(201602)->month; 2
150              
151             =head2 year
152              
153             Returns the year as an integer.
154              
155             say Month::Simple->new(201602)->year; 2016
156              
157             =head2 first_day
158              
159             Returns a L object for the first day of the month.
160              
161             =head2 last_day
162              
163             Returns a L object for the last day of the month.
164              
165             =head1 State of this module
166              
167             This module has been in production usage for quite some time, and is
168             considered complete in the sense that no more features are planned.
169              
170             =head1 AUTHOR
171              
172             Moritz Lenz, C<< >> for the noris network AG.
173              
174             =head1 BUGS
175              
176             Please report any bugs or feature requests to C, or through
177             the web interface at L. I will be notified, and then you'll
178             automatically be notified of progress on your bug as I make changes.
179              
180              
181             =head1 SUPPORT
182              
183             You can find documentation for this module with the perldoc command.
184              
185             perldoc Month::Simple
186              
187              
188             You can also look for information at:
189              
190             =over 4
191              
192             =item * RT: CPAN's request tracker (report bugs here)
193              
194             L
195              
196             =item * AnnoCPAN: Annotated CPAN documentation
197              
198             L
199              
200             =item * CPAN Ratings
201              
202             L
203              
204             =item * Search CPAN
205              
206             L
207              
208             =back
209              
210             =head1 LICENSE AND COPYRIGHT
211              
212             Copyright 2013 Moritz Lenz.
213              
214             This program is free software; you can redistribute it and/or modify it
215             under the terms of either: the GNU General Public License as published
216             by the Free Software Foundation; or the Artistic License.
217              
218             See L for more information.
219              
220              
221             =cut
222              
223             1; # End of Month::Simple