File Coverage

blib/lib/DateTime/Event/WarwickUniversity.pm
Criterion Covered Total %
statement 36 36 100.0
branch 8 8 100.0
condition 12 15 80.0
subroutine 8 8 100.0
pod 2 2 100.0
total 66 69 95.6


line stmt bran cond sub pod time code
1             package DateTime::Event::WarwickUniversity;
2              
3             =head1 NAME
4              
5             DateTime::Event::WarwickUniversity - Warwick University academic calendar events
6              
7             =head1 SYNOPSIS
8              
9             use DateTime::Event::WarwickUniversity;
10              
11             my $dt = DateTime->new(day => 7, month => 5, year => 2005);
12              
13             # 2005-09-26
14             my $dt_gr = DateTime::Event::Warwick->new_year_for_gregorian_year($dt);
15              
16             # 2004-09-28
17             my $dt_ac = DateTime::Event::Warwick->new_year_for_academic_year($dt);
18              
19             =head1 DESCRIPTION
20              
21             DateTime::Event::WarwickUniversity is used to work with the academic calendar
22             of the University of Warwick.
23              
24             =cut
25              
26 4     4   671079 use 5.008004;
  4         17  
  4         202  
27 4     4   26 use strict;
  4         10  
  4         149  
28 4     4   23 use warnings;
  4         11  
  4         150  
29 4     4   22 use Carp;
  4         9  
  4         567  
30 4     4   24 use Scalar::Util qw/blessed/;
  4         8  
  4         2644  
31              
32             our $VERSION = '0.05';
33              
34             # http://web.archive.org/web/19980114233111/warwick.ac.uk/info/dates.html
35             # http://web.archive.org/web/20001101110549/www.warwick.ac.uk/info/calendar/section1/1.01.html
36             # http://www2.warwick.ac.uk/insite/info/gov/calendar/section1/termdates/
37             # http://www2.warwick.ac.uk/services/gov/calendar/section1/termdates
38              
39             my %new_year = (
40             1996 => ['09', '30'],
41             1997 => ['09', '29'],
42             1998 => ['10', '05'],
43             1999 => ['10', '04'],
44             2000 => ['10', '02'],
45             2001 => ['10', '01'],
46             2002 => ['09', '30'],
47             2003 => ['09', '29'],
48             2004 => ['09', '28'],
49             2005 => ['09', '26'],
50             2006 => ['10', '02'],
51             2007 => ['10', '01'],
52             2008 => ['09', '29'],
53             2009 => ['10', '05'],
54             2010 => ['10', '04'],
55             2011 => ['10', '03'],
56             2012 => ['10', '01'],
57             2013 => ['09', '30'],
58             2014 => ['09', '29'],
59             2015 => ['10', '05'],
60             2016 => ['10', '03'],
61             2017 => ['10', '02'],
62             );
63              
64             my $min_year = 1996;
65             my $max_year = 2017;
66              
67             =head1 METHODS
68              
69             =head2 new_year_for_gregorian_year
70              
71             Takes as argument a single L object.
72              
73             Returns a L object representing the first day of the academic
74             calendar that begins in the same Gregorian year as the input.
75              
76             =cut
77              
78             sub new_year_for_gregorian_year {
79 9     9 1 459628 my ($class, $dt) = @_;
80              
81 9 100 100     179 croak("Input must be DateTime object")
      66        
82             unless ( defined($dt) && blessed($dt) && $dt->isa('DateTime') );
83              
84 7         35 my $dt_new_year = _new_year_dt_from_gregorian_year($dt->year);
85              
86             # Want to preserve input class/timezone/locale and don't want to alter
87             # input object, so use:
88             # new_year = input + ( new_year - input )
89              
90 5         1365 my $user_tz = $dt->time_zone;
91 5         43 my $clone = $dt->clone->set_time_zone('floating');
92              
93 5         1214 my $dt_dur = $dt_new_year->subtract_datetime_absolute( $clone );
94              
95 5         690 return $clone->add_duration( $dt_dur )->set_time_zone($user_tz);
96             }
97              
98             =head2 new_year_for_academic_year
99              
100             Takes as argument a single L object.
101              
102             Returns a L object representing the first day of the same academic
103             year as the input.
104              
105             =cut
106              
107             sub new_year_for_academic_year {
108 9     9 1 51796 my ($class, $dt) = @_;
109              
110 9 100 66     172 croak("Input must be DateTime object")
      66        
111             unless ( defined($dt) && blessed($dt) && $dt->isa('DateTime') );
112            
113 8         29 my $user_tz = $dt->time_zone;
114 8         63 my $clone = $dt->clone->set_time_zone('floating');
115              
116 8         1167 my $dt_new_year = _new_year_dt_from_gregorian_year($clone->year);
117 6         1066 my $dt_dur = $dt_new_year->subtract_datetime_absolute( $clone );
118              
119 6 100       651 if ($dt_dur->is_positive) {
120 3         81 $dt_new_year = _new_year_dt_from_gregorian_year($clone->year - 1);
121 3         560 $dt_dur = $dt_new_year->subtract_datetime_absolute( $clone );
122             }
123              
124 6         366 return $clone->add_duration( $dt_dur )->set_time_zone($user_tz);
125             }
126              
127             # _new_year_dt_from_gregorian_year
128             #
129             # Not part of public API. Takes a string containing a year, and returns a
130             # DateTime object representing the first day of the academic calendar that
131             # began in that Gregorian year.
132              
133             sub _new_year_dt_from_gregorian_year {
134 18     18   131 my $year = shift;
135              
136 18 100 100     147 croak("Input outside supported range.")
137             if ( $year < $min_year || $year > $max_year );
138              
139 14         40 my $date = $new_year{$year};
140              
141 14         66 return DateTime->new(
142             year => $year,
143             month => $date->[0],
144             day => $date->[1],
145             );
146             }
147              
148             1;
149             __END__