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