1package Time::Seconds;
2use strict;
3use vars qw/@EXPORT @EXPORT_OK/;
4
5our $VERSION = '1.27';
6
7use Exporter 5.57 'import';
8
9@EXPORT = qw(
10    ONE_MINUTE
11    ONE_HOUR
12    ONE_DAY
13    ONE_WEEK
14    ONE_MONTH
15    ONE_REAL_MONTH
16    ONE_YEAR
17    ONE_REAL_YEAR
18    ONE_FINANCIAL_MONTH
19    LEAP_YEAR
20    NON_LEAP_YEAR
21);
22
23@EXPORT_OK = qw(cs_sec cs_mon);
24
25use constant ONE_MINUTE => 60;
26use constant ONE_HOUR => 3_600;
27use constant ONE_DAY => 86_400;
28use constant ONE_WEEK => 604_800;
29use constant ONE_MONTH => 2_629_744; # ONE_YEAR / 12
30use constant ONE_REAL_MONTH => '1M';
31use constant ONE_YEAR => 31_556_930; # 365.24225 days
32use constant ONE_REAL_YEAR  => '1Y';
33use constant ONE_FINANCIAL_MONTH => 2_592_000; # 30 days
34use constant LEAP_YEAR => 31_622_400; # 366 * ONE_DAY
35use constant NON_LEAP_YEAR => 31_536_000; # 365 * ONE_DAY
36
37# hacks to make Time::Piece compile once again
38use constant cs_sec => 0;
39use constant cs_mon => 1;
40
41use overload
42                'fallback' => 'undef',
43                '0+' => \&seconds,
44                '""' => \&seconds,
45                '<=>' => \&compare,
46                '+' => \&add,
47                '-' => \&subtract,
48                '-=' => \&subtract_from,
49                '+=' => \&add_to,
50                '=' => \&copy;
51
52sub new {
53    my $class = shift;
54    my ($val) = @_;
55    $val = 0 unless defined $val;
56    bless \$val, $class;
57}
58
59sub _get_ovlvals {
60    my ($lhs, $rhs, $reverse) = @_;
61    $lhs = $lhs->seconds;
62
63    if (UNIVERSAL::isa($rhs, 'Time::Seconds')) {
64        $rhs = $rhs->seconds;
65    }
66    elsif (ref($rhs)) {
67        die "Can't use non Seconds object in operator overload";
68    }
69
70    if ($reverse) {
71        return $rhs, $lhs;
72    }
73
74    return $lhs, $rhs;
75}
76
77sub compare {
78    my ($lhs, $rhs) = _get_ovlvals(@_);
79    return $lhs <=> $rhs;
80}
81
82sub add {
83    my ($lhs, $rhs) = _get_ovlvals(@_);
84    return Time::Seconds->new($lhs + $rhs);
85}
86
87sub add_to {
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
95sub subtract {
96    my ($lhs, $rhs) = _get_ovlvals(@_);
97    return Time::Seconds->new($lhs - $rhs);
98}
99
100sub subtract_from {
101    my $lhs = shift;
102    my $rhs = shift;
103    $rhs = $rhs->seconds if UNIVERSAL::isa($rhs, 'Time::Seconds');
104    $$lhs -= $rhs;
105    return $lhs;
106}
107
108sub copy {
109	Time::Seconds->new(${$_[0]});
110}
111
112sub seconds {
113    my $s = shift;
114    return $$s;
115}
116
117sub minutes {
118    my $s = shift;
119    return $$s / 60;
120}
121
122sub hours {
123    my $s = shift;
124    $s->minutes / 60;
125}
126
127sub days {
128    my $s = shift;
129    $s->hours / 24;
130}
131
132sub weeks {
133    my $s = shift;
134    $s->days / 7;
135}
136
137sub months {
138    my $s = shift;
139    $s->days / 30.4368541;
140}
141
142sub financial_months {
143    my $s = shift;
144    $s->days / 30;
145}
146
147sub years {
148    my $s = shift;
149    $s->days / 365.24225;
150}
151
152sub pretty {
153    my $s = shift;
154    my $str = "";
155    if ($s < 0) {
156        $s = -$s;
157        $str = "minus ";
158    }
159    if ($s >= ONE_MINUTE) {
160        if ($s >= ONE_HOUR) {
161            if ($s >= ONE_DAY) {
162                my $days = sprintf("%d", $s->days); # does a "floor"
163                $str = $days . " days, ";
164                $s -= ($days * ONE_DAY);
165            }
166            my $hours = sprintf("%d", $s->hours);
167            $str .= $hours . " hours, ";
168            $s -= ($hours * ONE_HOUR);
169        }
170        my $mins = sprintf("%d", $s->minutes);
171        $str .= $mins . " minutes, ";
172        $s -= ($mins * ONE_MINUTE);
173    }
174    $str .= $s->seconds . " seconds";
175    return $str;
176}
177
1781;
179__END__
180
181=encoding utf8
182
183=head1 NAME
184
185Time::Seconds - a simple API to convert seconds to other date values
186
187=head1 SYNOPSIS
188
189    use Time::Piece;
190    use Time::Seconds;
191
192    my $t = localtime;
193    $t += ONE_DAY;
194
195    my $t2 = localtime;
196    my $s = $t - $t2;
197
198    print "Difference is: ", $s->days, "\n";
199
200=head1 DESCRIPTION
201
202This module is part of the Time::Piece distribution. It allows the user
203to find out the number of minutes, hours, days, weeks or years in a given
204number of seconds. It is returned by Time::Piece when you delta two
205Time::Piece objects.
206
207Time::Seconds also exports the following constants:
208
209    ONE_DAY
210    ONE_WEEK
211    ONE_HOUR
212    ONE_MINUTE
213    ONE_MONTH
214    ONE_YEAR
215    ONE_FINANCIAL_MONTH
216    LEAP_YEAR
217    NON_LEAP_YEAR
218
219Since perl does not (yet?) support constant objects, these constants are in
220seconds only, so you cannot, for example, do this: C<print ONE_WEEK-E<gt>minutes;>
221
222=head1 METHODS
223
224The following methods are available:
225
226    my $val = Time::Seconds->new(SECONDS)
227    $val->seconds;
228    $val->minutes;
229    $val->hours;
230    $val->days;
231    $val->weeks;
232	$val->months;
233	$val->financial_months; # 30 days
234    $val->years;
235    $val->pretty; # gives English representation of the delta
236
237The usual arithmetic (+,-,+=,-=) is also available on the objects.
238
239The methods make the assumption that there are 24 hours in a day, 7 days in
240a week, 365.24225 days in a year and 12 months in a year.
241(from The Calendar FAQ at http://www.tondering.dk/claus/calendar.html)
242
243=head1 AUTHOR
244
245Matt Sergeant, matt@sergeant.org
246
247Tobias Brox, tobiasb@tobiasb.funcom.com
248
249Balázs Szabó (dLux), dlux@kapu.hu
250
251=head1 COPYRIGHT AND LICENSE
252
253Copyright 2001, Larry Wall.
254
255This module is free software, you may distribute it under the same terms
256as Perl.
257
258=head1 Bugs
259
260Currently the methods aren't as efficient as they could be, for reasons of
261clarity. This is probably a bad idea.
262
263=cut
264