C<$foo =~ give_me_a_regex>; /x modifier
[p5sagit/p5-mst-13.2.git] / ext / Time / Piece / Seconds.pm
1 package Time::Seconds;
2 use strict;
3 use vars qw/@EXPORT @ISA/;
4
5 @ISA = 'Exporter';
6
7 @EXPORT = qw(
8                 ONE_MINUTE 
9                 ONE_HOUR 
10                 ONE_DAY 
11                 ONE_WEEK 
12                 ONE_MONTH
13                 ONE_YEAR
14                 ONE_FINANCIAL_MONTH
15                 LEAP_YEAR 
16                 NON_LEAP_YEAR
17                 );
18
19 use constant ONE_MINUTE => 60;
20 use constant ONE_HOUR => 3_600;
21 use constant ONE_DAY => 86_400;
22 use constant ONE_WEEK => 604_800;
23 use constant ONE_MONTH => 2_629_744; # ONE_YEAR / 12
24 use constant ONE_YEAR => 31_556_930; # 365.24225 days
25 use constant ONE_FINANCIAL_MONTH => 2_592_000; # 30 days
26 use constant LEAP_YEAR => 31_622_400; # 366 * ONE_DAY
27 use constant NON_LEAP_YEAR => 31_536_000; # 365 * ONE_DAY
28
29 use overload 
30                 '0+' => \&seconds,
31                 '""' => \&seconds,
32                 '<=>' => \&compare,
33                 '+' => \&add,
34                 '-' => \&subtract,
35                 '-=' => \&subtract_from,
36                 '+=' => \&add_to,
37                 '=' => \&copy;
38
39 sub new {
40         my $class = shift;
41         my ($val) = @_;
42         $val = 0 unless defined $val;
43         bless \$val, $class;
44 }
45
46 sub _get_ovlvals {
47         my ($lhs, $rhs, $reverse) = @_;
48         $lhs = $lhs->seconds;
49         
50         if (UNIVERSAL::isa($rhs, 'Time::Seconds')) {
51                 $rhs = $rhs->seconds;
52         }
53         elsif (ref($rhs)) {
54                 die "Can't use non Seconds object in operator overload";
55         }
56         
57         if ($reverse) {
58                 return $rhs, $lhs;
59         }
60         
61         return $lhs, $rhs;
62 }
63
64 sub compare {
65         my ($lhs, $rhs) = _get_ovlvals(@_);
66         return $lhs <=> $rhs;
67 }
68
69 sub add {
70         my ($lhs, $rhs) = _get_ovlvals(@_);
71         return Time::Seconds->new($lhs + $rhs);
72 }
73
74 sub add_to {
75         my $lhs = shift;
76         my $rhs = shift;
77         $rhs = $rhs->seconds if UNIVERSAL::isa($rhs, 'Time::Seconds');
78         $$lhs += $rhs;
79         return $lhs;
80 }
81
82 sub subtract {
83         my ($lhs, $rhs) = _get_ovlvals(@_);
84         return Time::Seconds->new($lhs - $rhs);
85 }
86
87 sub subtract_from {
88         my $lhs = shift;
89         my $rhs = shift;
90         $rhs = $rhs->seconds if UNIVERSAL::isa($rhs, 'Time::Seconds');
91         $$lhs -= $rhs;
92         return $lhs;
93 }
94
95 sub copy {
96         Time::Seconds->new(${$_[0]});
97 }
98
99 sub seconds {
100         my $s = shift;
101         $$s;
102 }
103
104 sub minutes {
105         my $s = shift;
106         $$s / 60;
107 }
108
109 sub hours {
110         my $s = shift;
111         $s->minutes / 60;
112 }
113
114 sub days {
115         my $s = shift;
116         $s->hours / 24;
117 }
118
119 sub weeks {
120         my $s = shift;
121         $s->days / 7;
122 }
123
124 sub months {
125         my $s = shift;
126         $s->days / 30.4368541;
127 }
128
129 sub financial_months {
130         my $s = shift;
131         $s->days / 30;
132 }
133
134 *f_months = \&financial_months;
135
136 sub years {
137         my $s = shift;
138         $s->days / 365.24225;
139 }
140
141 1;
142 __END__
143
144 =head1 NAME
145
146 Time::Seconds - a simple API to convert seconds to other date values
147
148 =head1 SYNOPSIS
149
150     use Time::Piece;
151     use Time::Seconds;
152     
153     my $t = localtime;
154     $t += ONE_DAY;
155     
156     my $t2 = localtime;
157     my $s = $t - $t2;
158     
159     print "Difference is: ", $s->days, "\n";
160
161 =head1 DESCRIPTION
162
163 This module is part of the Time::Piece distribution. It allows the user
164 to find out the number of minutes, hours, days, weeks or years in a given
165 number of seconds. It is returned by Time::Piece when you delta two
166 Time::Piece objects.
167
168 Time::Seconds also exports the following constants:
169
170     ONE_DAY
171     ONE_WEEK
172     ONE_HOUR
173     ONE_MINUTE
174         ONE_MONTH
175         ONE_YEAR
176         ONE_FINANCIAL_MONTH
177     LEAP_YEAR
178     NON_LEAP_YEAR
179
180 Since perl does not (yet?) support constant objects, these constants
181 are in seconds only, so you cannot, for example, do this: C<print
182 ONE_WEEK-E<gt>minutes;>
183
184 =head1 METHODS
185
186 The following methods are available:
187
188     my $val = Time::Seconds->new(SECONDS)
189     $val->seconds;
190     $val->minutes;
191     $val->hours;
192     $val->days;
193     $val->weeks;
194         $val->months;
195         $val->financial_months; # 30 days
196     $val->years;
197
198 The methods make the assumption that there are 24 hours in a day, 7 days in
199 a week, 365.24225 days in a year and 12 months in a year.
200 (from The Calendar FAQ at http://www.tondering.dk/claus/calendar.html)
201
202 =head1 AUTHOR
203
204 Matt Sergeant, matt@sergeant.org
205
206 Tobias Brox, tobiasb@tobiasb.funcom.com
207
208 =head1 LICENSE
209
210 Please see Time::Piece for the license.
211
212 =head1 Bugs
213
214 Currently the methods aren't as efficient as they could be, for reasons of
215 clarity. This is probably a bad idea.
216
217 =cut