File Coverage

blib/lib/Date/Simple.pm
Criterion Covered Total %
statement 72 91 79.1
branch 22 38 57.8
condition 13 24 54.1
subroutine 24 28 85.7
pod 14 14 100.0
total 145 195 74.3


line stmt bran cond sub pod time code
1             # Date::Simple - a simple date object
2              
3             package Date::Simple;
4              
5             BEGIN {
6 3     3   55875 $VERSION = '3.03';
7             }
8              
9 3     3   23 use Exporter ();
  3         8  
  3         485  
10             @ISA = ('Exporter');
11              
12             @EXPORT_OK = qw(
13             today ymd d8 leap_year days_in_month
14             date date_fmt date_d8 date_iso
15             );
16              
17             %EXPORT_TAGS = ( 'all' => \@EXPORT_OK );
18              
19             # Try to load the C code. If that fails, fall back to Date::Simple::NoXS.
20             if ( !defined(&_add) ) {
21             my $err = $Date::Simple::NoXS;
22             unless ($err) {
23              
24             # Use DynaLoader instead of XSLoader for pre-5.005.
25             local ($@);
26             local @ISA = ('DynaLoader');
27             require DynaLoader;
28             eval { __PACKAGE__->bootstrap($VERSION); };
29             $err = $@;
30             }
31             if ($err) {
32             $Date::Simple::NoXs = 1;
33             require Date::Simple::NoXS;
34             }
35             }
36              
37 3     3   18 use strict;
  3         6  
  3         126  
38 3     3   21 use Carp ();
  3         6  
  3         304  
39             use overload
40             '+' => '_add',
41             '-' => '_subtract',
42             '==' => '_eq',
43             '!=' => '_ne',
44             '<=>' => '_compare',
45             'eq' => '_eq',
46             'ne' => '_ne',
47             'cmp' => '_compare',
48 68     68   521 'bool' => sub { 1 },
49 3     3   7427 '""' => 'as_iso';
  3         3909  
  3         39  
50              
51 3     3   756 use Scalar::Util qw(refaddr reftype);
  3         7  
  3         486  
52 3     3   18 use warnings::register;
  3         6  
  3         5017  
53             require Date::Simple::Fmt;
54             require Date::Simple::ISO;
55             require Date::Simple::D8;
56              
57             sub d8 {
58              
59             # called as function
60 6 50   6 1 19 if ( $#_ == 0 ) {
61 6         55 return __PACKAGE__->_d8(@_);
62             }
63              
64             # called as method
65             else {
66 0 0       0 if ( ref $_[0] eq 'SCALAR' ) {
67 0         0 return $_[0]->SUPER::_d8(@_);
68             }
69             else {
70 0         0 return $_[0]->_d8(@_);
71             }
72             }
73             }
74              
75             sub today {
76 1 50   1 1 5 if ( $#_ == -1 ) {
77 1         6 return __PACKAGE__->_today(@_);
78             }
79             else {
80 0         0 return shift->_today(@_);
81             }
82             }
83              
84             sub ymd {
85              
86             # called as function
87 33 50   33 1 87 if ( $#_ == 2 ) {
88 33         301 return __PACKAGE__->_ymd(@_);
89             }
90              
91             # called as method
92             else {
93 0 0       0 if ( ref $_[0] eq 'SCALAR' ) {
94 0         0 return $_[0]->SUPER::_ymd(@_);
95             }
96             else {
97 0         0 return $_[0]->_ymd(@_);
98             }
99             }
100             }
101              
102             sub _today {
103 6     6   626 my ( $y, $m, $d ) = (localtime)[ 5, 4, 3 ];
104 6         16 $y += 1900;
105 6         11 $m += 1;
106 6         83 return $_[0]->_ymd( $y, $m, $d );
107             }
108              
109             sub _inval {
110 0     0   0 my ($first);
111 0         0 $first = shift;
112 0   0     0 Carp::croak( "Invalid "
113             . ( ref($first) || $first )
114             . " constructor args: ('"
115             . join( "', '", @_ )
116             . "')" );
117             }
118              
119             sub _new {
120 66     66   494 my ( $that, @ymd ) = @_;
121              
122 66   66     262 my $class = ref($that) || $that;
123              
124 66 100       159 if ( @ymd == 1 ) {
125 28         40 my $x = $ymd[0];
126 28 100 66     320 if ( ref $x and reftype($x) eq 'ARRAY' ) {
    50 100        
    100          
127 2         6 @ymd = @$x;
128             }
129             elsif ( UNIVERSAL::isa( $x, __PACKAGE__ ) ) {
130 0         0 return ($x);
131             }
132             elsif ($x =~ /^(\d\d\d\d)-(\d\d)-(\d\d)$/
133             || $x =~ /^(\d\d\d\d)(\d\d)(\d\d)$/ ) {
134 24         113 @ymd = ( $1, $2, $3 );
135             }
136             else {
137 2         11 return (undef);
138             }
139             } # we fall through here...
140              
141             # note we can end up here is they pass in [] as the date
142 64 100       177 return $class->_today() unless @ymd;
143              
144             # to get here, we had one arg which was split,
145             # or 3 in the first place
146 60 50       196 if ( @ymd == 3 ) {
147 60         259 my $days = ymd_to_days(@ymd);
148 60 100       157 return undef if !defined($days);
149 42         220 return ( bless( \$days, $class ) );
150             }
151              
152 0         0 $class->_inval(@ymd);
153             }
154              
155 2     2 1 8 sub date { scalar __PACKAGE__->_new(@_) }
156              
157             sub date_fmt {
158 0     0 1 0 my $format = shift;
159 0         0 my $obj = Date::Simple::Fmt->_new(@_);
160 0 0       0 $obj->default_format($format)
161             if $obj;
162 0         0 $obj;
163             }
164              
165 0     0 1 0 sub date_d8 { scalar Date::Simple::D8->_new(@_) }
166 0     0 1 0 sub date_iso { scalar Date::Simple::ISO->_new(@_) }
167              
168             # Same as date() but it's a method and croaks on error if called with
169             # one arg.
170             sub new {
171 55     55 1 5597 my ( $class, $date );
172              
173 55         121 $date = &_new;
174 55 50 66     633 if ( !$date && scalar(@_) == 1 ) {
175 0         0 Carp::croak( "'" . shift() . "' is not a valid ISO formated date" );
176             }
177 55         235 return ($date);
178             }
179              
180 2     2 1 11 sub next { return ( $_[0] + 1 ); }
181 2     2 1 12 sub prev { return ( $_[0] - 1 ); }
182              
183             sub _gmtime {
184 32     32   51 my ( $y, $m, $d ) = days_to_ymd( ${ $_[0] } );
  32         129  
185 32         51 $y -= 1900;
186 32         43 $m -= 1;
187 32         948 return ( 0, 0, 0, $d, $m, $y );
188             }
189              
190             BEGIN {
191 3     3   8 our $Standard_Format = "%Y-%m-%d";
192 3         500 my %fmts = ( # Inside out parameter
193             'Date::Simple' => $Standard_Format,
194             'Date::Simple::ISO' => $Standard_Format,
195             'Date::Simple::D8' => "%Y%m%d",
196             'Date::Simple::Fmt' => $Standard_Format,
197             );
198              
199             sub format {
200 32     32 1 66 my ( $self, $format ) = @_;
201              
202 32 100 33     170 $format =
203             $fmts{ refaddr($self) || '' }
204             || $fmts{ ref($self) }
205             || $Standard_Format
206             if @_ == 1;
207              
208 32 50       91 return "$self" unless defined($format);
209 32         2440 require POSIX;
210 32         15942 local $ENV{TZ} = 'UTC+0';
211 32         87 return POSIX::strftime( $format, _gmtime($self) );
212             }
213              
214 15     15 1 39 sub strftime { &format }
215 11     11 1 29 sub as_str { &format }
216              
217             sub default_format {
218 43     43 1 78 my ( $self, $val ) = @_;
219              
220 43   33     139 my $o = refaddr($self) || $self;
221              
222 43 100       113 if ( @_ > 1 ) {
223 23         79 $fmts{$o} = $val;
224 23 0       64 warnings::warnif "Setting class specific date format '$o' to" . "'"
    50          
225             . ( defined $val ? $val : 'undef' ) . "'"
226             unless ref $self;
227             }
228              
229 43   66     229 return $fmts{$o} || $Standard_Format;
230             }
231              
232             sub DESTROY {
233 109     109   4117 delete $fmts{ refaddr $_[0] };
234             }
235             }
236              
237             1;
238              
239             =head1 NAME
240              
241             Date::Simple - a simple date object
242              
243             =head1 SYNOPSIS
244              
245             use Date::Simple ('date', 'today');
246              
247             # Difference in days between two dates:
248             $diff = date('2001-08-27') - date('1977-10-05');
249              
250             # Offset $n days from now:
251             $date = today() + $n;
252             print "$date\n"; # uses ISO 8601 format (YYYY-MM-DD)
253              
254             use Date::Simple ();
255             my $date = Date::Simple->new('1972-01-17');
256             my $year = $date->year;
257             my $month = $date->month;
258             my $day = $date->day;
259              
260             use Date::Simple (':all');
261             my $date2 = ymd($year, $month, $day);
262             my $date3 = d8('19871218');
263             my $today = today();
264             my $tomorrow = $today + 1;
265             if ($tomorrow->year != $today->year) {
266             print "Today is New Year's Eve!\n";
267             }
268              
269             if ($today > $tomorrow) {
270             die "warp in space-time continuum";
271             }
272              
273             print "Today is ";
274             print(('Sun','Mon','Tues','Wednes','Thurs','Fri','Satur')
275             [$today->day_of_week]);
276             print "day.\n";
277              
278             # you can also do this:
279             ($date cmp "2001-07-01")
280             # and this
281             ($date <=> [2001, 7, 1])
282              
283             =begin text
284              
285             INSTALLATION
286              
287             If your system has the "make" program or a clone:
288              
289             perl Makefile.PL
290             make
291             make test
292             make install
293              
294             If you lack "make", copy the "lib/Date" directory to your module
295             directory (run "perl -V:sitelib" to find it).
296              
297             If "make test" fails, perhaps it means your system can't compile C
298             code. Try:
299              
300             make distclean
301             perl Makefile.PL noxs
302             make
303             make test
304             make install
305              
306             This will use the pure-Perl implementation.
307              
308             =end text
309              
310             =head1 DESCRIPTION
311              
312             Dates are complex enough without times and timezones. This module may
313             be used to create simple date objects. It handles:
314              
315             =over 4
316              
317             =item Validation.
318              
319             Reject 1999-02-29 but accept 2000-02-29.
320              
321             =item Interval arithmetic.
322              
323             How many days were between two given dates? What date comes N days
324             after today?
325              
326             =item Day-of-week calculation.
327              
328             What day of the week is a given date?
329              
330             =item Transparent date formatting.
331              
332             How should a date object be formatted.
333              
334             =back
335              
336             It does B deal with hours, minutes, seconds, and time zones.
337              
338             A date is uniquely identified by year, month, and day integers within
339             valid ranges. This module will not allow the creation of objects for
340             invalid dates. Attempting to create an invalid date will return
341             undef. Month numbering starts at 1 for January, unlike in C and Java.
342             Years are 4-digit.
343              
344             Gregorian dates up to year 9999 are handled correctly, but we rely on
345             Perl's builtin C function when the current date is
346             requested. On some platforms, C may be vulnerable to
347             rollovers such as the Unix C wraparound of 18 January 2038.
348              
349             Overloading is used so you can compare or subtract two dates using
350             standard numeric operators such as C<==>, and the sum of a date object
351             and an integer is another date object.
352              
353             Date::Simple objects are immutable. After assigning C<$date1> to
354             C<$date2>, no change to C<$date1> can affect C<$date2>. This means,
355             for example, that there is nothing like a C operation, and
356             C<$date++> assigns a new object to C<$date>.
357              
358             This module contains various undocumented functions. They may not be
359             available on all platforms and are likely to change or disappear in
360             future releases. Please let the author know if you think any of them
361             should be public.
362              
363             =head2 Controlling output format.
364              
365             As of version 3.0 new ways of controlling the output formats of Date::Simple
366             objects has been provided. However Date::Simple has traditionally provided
367             few ways of stringification, a primary one via the format() method and another
368             primary one via direct stringification. However the later is currently
369             implemented as an XS routine and the former is implemented through a perl routine.
370             This means that using format() is more expensive than stringification and
371             that the stringification format is class specific.
372              
373             In order to alleviate some of these problems a new mechanism has been introduced
374             to Date::Simple that allows for a per object level format default. In addition
375             a set of utility classes that have different stringification overloads provided.
376             These classes are simple subclasses of Date::Simple and beside the default format()
377             and the overloaded stringification behaviour are identical to Date::Simple. In fact
378             one is totally identical to Date::Simple and is provided mostly for completeness.
379              
380             The classes included are:
381              
382             =over 4
383              
384             =item Date::Simple::ISO
385              
386             Identical to Date::Simple in every respect but name.
387              
388             =item Date::Simple::D8
389              
390             Uses the D8 format (%Y%m%d) as the default format for printing. Uses XS for the
391             overloaded stringification.
392              
393             =item Date::Simple::Fmt
394              
395             Uses the perl implemented format() as the default stringification mechanism. The first
396             argument to the constructor is expected to be the format to use for the object.
397              
398             =back
399              
400             B its important to remember that the primary difference between the behaviour
401             of objects of the different classes is how they are stringified when quoted, and what
402             date format is used by default when the format() method is called. Nothing else differs.
403              
404             =head1 CONSTRUCTORS
405              
406             Several functions take a string or numeric representation and generate
407             a corresponding date object. The most general is C, whose
408             argument list may be empty (returning the current date), a string in
409             format YYYY-MM-DD or YYYYMMDD, a list or arrayref of year, month, and
410             day number, or an existing date object.
411              
412             =over 4
413              
414             =item Date::Simple->new ([ARG, ...])
415              
416             =item date ([ARG, ...])
417              
418             my $date = Date::Simple->new('1972-01-17');
419              
420             The C method will return a date object if the values passed in
421             specify a valid date. (See above.) If an invalid date is passed, the
422             method returns undef. If the argument is invalid in form as opposed
423             to numeric range, C dies.
424              
425             The C function provides the same functionality but must be
426             imported or qualified as C. (To import all public
427             functions, do C.) This function returns
428             undef on all invalid input, rather than dying in some cases like
429             C.
430              
431             =item date_fmt (FMT,[ARG, ...])
432              
433             Equivelent to C but creates a Date::Simple::Fmt object instead. The
434             format is expected to be a valid POSIX::strftime format string.
435              
436             =item date_iso ([ARG, ...])
437              
438             Identical to C but creates a Date::Simple::ISO object instead.
439              
440             =item date_d8 ([ARG, ...])
441              
442             Equivelent to C but creates a Date::Simple::D8 object instead.
443              
444             =item today()
445              
446             Returns the current date according to C.
447              
448             B To get tomorrow's date (or any fixed offset from today),
449             do not use C. Perl parses this as C. You need
450             to put empty parentheses after the function: C.
451              
452             =item ymd (YEAR, MONTH, DAY)
453              
454             Returns a date object with the given year, month, and day numbers. If
455             the arguments do not specify a valid date, undef is returned.
456              
457             Example:
458              
459             use Date::Simple ('ymd');
460             $pbd = ymd(1987, 12, 18);
461              
462             =item d8 (STRING)
463              
464             Parses STRING as "YYYYMMDD" and returns the corresponding date object,
465             or undef if STRING has the wrong format or specifies an invalid date.
466              
467             Example:
468              
469             use Date::Simple ('d8');
470             $doi = d8('17760704');
471              
472             Mnemonic: The string matches C. Also, "d8" spells "date", if
473             8 is expanded phonetically.
474              
475             =back
476              
477             =head1 INSTANCE METHODS
478              
479             =over 4
480              
481             =item DATE->next
482              
483             my $tomorrow = $today->next;
484              
485             Returns an object representing tomorrow.
486              
487             =item DATE->prev
488              
489             my $yesterday = $today->prev;
490              
491             Returns an object representing yesterday.
492              
493             =item DATE->year
494              
495             my $year = $date->year;
496              
497             Return the year of DATE as an integer.
498              
499             =item DATE->month
500              
501             my $month = $date->month;
502              
503             Return the month of DATE as an integer from 1 to 12.
504              
505             =item DATE->day
506              
507             my $day = $date->day;
508              
509             Return the DATE's day of the month as an integer from 1 to 31.
510              
511             =item DATE->day_of_week
512              
513             Return a number representing DATE's day of the week from 0 to 6, where
514             0 means Sunday.
515              
516             =item DATE->as_ymd
517              
518             my ($year, $month, $day) = $date->as_ymd;
519              
520             Returns a list of three numbers: year, month, and day.
521              
522             =item DATE->as_d8
523              
524             Returns the "d8" representation (see C), like
525             C<$date-Eformat("%Y%m%d")>.
526              
527             =item DATE->as_iso
528              
529             Returns the ISO 8601 representation of the date (eg '2004-01-01'),
530             like C<$date-Eformat("%Y-%m-%d")>. This is in fact the default
531             overloaded stringification mechanism and is provided mostly so
532             other subclasses with different overloading can still do fast
533             ISO style date output.
534              
535             =item DATE->as_str ([STRING])
536              
537             =item DATE->format ([STRING])
538              
539             =item DATE->strftime ([STRING])
540              
541             These functions are equivalent. Return a string representing the
542             date, in the format specified. If you don't pass a parameter, the default
543             date format for the object is used if one has been specified, otherwise
544             uses the default date format for the class the object is a member of, or as
545             a last fallback uses the $Date::Simple::Standard_Format which is changeable,
546             but probably shouldn't be modified. See C for details.
547              
548             my $change_date = $date->format("%d %b %y");
549             my $iso_date1 = $date->format("%Y-%m-%d");
550             my $iso_date2 = $date->format;
551              
552             The formatting parameter is similar to one you would pass to
553             strftime(3). This is because we actually do pass it to strftime to
554             format the date. This may result in differing behavior across
555             platforms and locales and may not even work everywhere.
556              
557             =item DATE->default_format ([FORMAT])
558              
559             This method sets or gets the default_format for the DATE object or class
560             that it is called on.
561              
562             =back
563              
564             =head1 OPERATORS
565              
566             Some operators can be used with Date::Simple instances. If one side
567             of an expression is a date object, and the operator expects two date
568             objects, the other side is interpreted as C, so an array
569             reference or ISO 8601 string will work.
570              
571             =over 4
572              
573             =item DATE + NUMBER
574              
575             =item DATE - NUMBER
576              
577             You can construct a new date offset by a number of days using the C<+>
578             and C<-> operators.
579              
580             =item DATE1 - DATE2
581              
582             You can subtract two dates to find the number of days between them.
583              
584             =item DATE1 == DATE2
585              
586             =item DATE1 < DATE2
587              
588             =item DATE1 <=> DATE2
589              
590             =item DATE1 cmp DATE2
591              
592             =item etc.
593              
594             You can compare two dates using the arithmetic or string comparison
595             operators. Equality tests (C<==> and C) return false when one of
596             the expressions can not be converted to a date. Other comparison
597             tests die in such cases. This is intentional, because in a sense, all
598             non-dates are not "equal" to all dates, but in no sense are they
599             "greater" or "less" than dates.
600              
601             =item DATE += NUMBER
602              
603             =item DATE -= NUMBER
604              
605             You can increment or decrement a date by a number of days using the +=
606             and -= operators. This actually generates a new date object and is
607             equivalent to C<$date = $date + $number>.
608              
609             =item "$date"
610              
611             You can interpolate a date instance directly into a string, in the
612             format specified by ISO 8601 (eg: 2000-01-17) for Date::Simple and
613             Date::Simple::ISO, for Date::Simple::D8 this is the same as calling
614             as_d8() on the object, and for Date::Simple::Fmt this is the same as
615             calling format() on the object.
616              
617             =back
618              
619             =head1 UTILITIES
620              
621             =over 4
622              
623             =item leap_year (YEAR)
624              
625             Returns true if YEAR is a leap year.
626              
627             =item days_in_month (YEAR, MONTH)
628              
629             Returns the number of days in MONTH, YEAR.
630              
631             =back
632              
633             =over 4
634              
635             =item leap_year (YEAR)
636              
637             Returns true if YEAR is a leap year.
638              
639             =item days_in_month (YEAR, MONTH)
640              
641             Returns the number of days in MONTH, YEAR.
642              
643             =back
644              
645              
646             =head1 AUTHOR
647              
648             Marty Pauley
649             John Tobey
650             Yves Orton
651              
652             =head1 COPYRIGHT
653              
654             Copyright (C) 2001 Kasei.
655             Copyright (C) 2001,2002 John Tobey.
656             Copyright (C) 2004 Yves Orton.
657              
658             This program is free software; you can redistribute it and/or
659             modify it under the terms of either:
660              
661             a) the GNU General Public License;
662             either version 2 of the License, or (at your option) any later
663             version. You should have received a copy of the GNU General
664             Public License along with this program; see the file COPYING.
665             If not, write to the Free Software Foundation, Inc., 59
666             Temple Place, Suite 330, Boston, MA 02111-1307 USA
667              
668             b) the Perl Artistic License.
669              
670             This program is distributed in the hope that it will be useful,
671             but WITHOUT ANY WARRANTY; without even the implied warranty of
672             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
673              
674             =head1 SEE ALSO
675              
676             L L L
677             and of course L
678              
679             =cut