File Coverage

blib/lib/Date/Components.pm
Criterion Covered Total %
statement 1304 1369 95.2
branch 972 974 99.7
condition 207 213 97.1
subroutine 50 50 100.0
pod 44 44 100.0
total 2577 2650 97.2


line stmt bran cond sub pod time code
1             {
2             package Date::Components;
3              
4 46     46   1534296 use 5.008008;
  46         186  
  46         3641  
5 46     46   280 use strict;
  46         100  
  46         2133  
6 46     46   318 use warnings;
  46         115  
  46         4286  
7              
8             require Exporter;
9              
10             our @ISA = qw(Exporter);
11              
12 46     46   289 eval {use Carp qw(croak)};
  46         109  
  46         5062  
13 46     46   58275 eval {use Readonly};
  46         198007  
  46         25721  
14              
15             our @EXPORT = qw();
16              
17             # Items to export into callers namespace by default. Note: do not export
18             # names by default without a very good reason. Use EXPORT_OK instead.
19             # Do not simply export all your public functions/methods/constants.
20             our @EXPORT_OK = ( qw(
21             date_only_parse
22             is_valid_date
23             format_date
24             is_leap_year
25             is_valid_month
26             is_valid_day_of_month
27             is_valid_day_of_week
28             is_valid_year
29             is_valid_400_year_cycle
30             get_year_phase
31             number_of_day_within_year
32             day_number_within_year_to_date
33             day_number_within_400_year_cycle_to_date
34             get_number_of_day_within_400yr_cycle
35             get_days_remaining_in_400yr_cycle
36             day_name_to_day_number
37             day_number_to_day_name
38             get_num_days_in_year
39             get_days_remaining_in_year
40             get_numeric_day_of_week
41             get_month_from_string
42             get_dayofmonth_from_string
43             get_year_from_string
44             get_number_of_days_in_month
45             get_days_remaining_in_month
46             get_first_of_month_day_of_week
47             month_name_to_month_number
48             month_number_to_month_name
49             set_day_to_day_name_abbrev
50             set_day_to_day_name_full
51             set_day_to_day_number
52             set_month_to_month_name_abbrev
53             set_month_to_month_name_full
54             set_month_to_month_number
55             date1_to_date2_delta
56             number_of_weekdays_in_range
57             compare_date1_and_date2
58             year1_to_year2_delta
59             compare_year1_and_year2
60             date_offset_in_days
61             date_offset_in_weekdays
62             date_offset_in_years
63             calculate_day_of_week_for_first_of_month_in_next_year
64             get_global_year_cycle
65             ),
66             );
67              
68             # This allows declaration use Date::Components ':all';
69             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
70             # will save memory.
71             our %EXPORT_TAGS = (
72             'all' => [ @EXPORT_OK, @EXPORT ],
73             );
74              
75 46     46   52311 use version; our $VERSION = qv('0.2.1');
  46         133128  
  46         406  
76              
77              
78             # According to the Royal Greenwich Observatory, the calendar year is 365 days
79             # long, unless the year is exactly divisible by four, then an extra day is
80             # added to February so the year is 366 days long. If the year is the last year
81             # of a century, e.g., 2000, 2100, 2200, 2300, 2400, then it is only a leap
82             # year if it is exactly divisible by 400. So, 2100 won't be a leap year but
83             # 2000 is. The next century year, exactly divisible by 400, won't occur until
84             # 2400--400 years away.
85              
86              
87              
88              
89              
90              
91              
92             Readonly my $DATE_BASELINE_YEAR_2000 => '2000';
93             #Readonly my $DATE_BASELINE_MONTHNUM => '1';
94             #Readonly my $DATE_BASELINE_MONTHNAME => 'January';
95             #Readonly my $DATE_BASELINE_DAYNUM => '6';
96             #Readonly my $DATE_BASELINE_DAYNAME => 'Saturday';
97             Readonly my $NUMBER_OF_YEAR_PHASES => 400;
98             #Readonly my $MIN_NUMBER_OF_DAYS_IN_YEAR => 365;
99             #Readonly my $MAX_NUMBER_OF_DAYS_IN_YEAR => 366;
100             #Readonly my $MIN_NUMBER_OF_DAYS_IN_A_MONTH => 28;
101             #Readonly my $NUMBER_OF_MONTHS_IN_YEAR => 12;
102              
103             Readonly my $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE => (300 * 365) + (100 * 366) - 3; # three is subtracted for the three of the four century years which are NOT leap years
104             Readonly my $BASELINE_DAY_OF_WEEK_ON_JAN_1_2000 => 6;
105              
106              
107              
108             # Create READ ONLY hash to hold day of week on Jan 1 for each year phase
109             my %hash_intermediate_00;
110             $hash_intermediate_00{'0'} = $BASELINE_DAY_OF_WEEK_ON_JAN_1_2000;
111             for ( my $iii_003=1; $iii_003<$NUMBER_OF_YEAR_PHASES; $iii_003++ )
112             {
113             my $num_days_in_year_05 = get_num_days_in_year($iii_003 - 1);
114             $hash_intermediate_00{$iii_003} = calculate_day_of_week_for_first_of_month_in_next_year( $num_days_in_year_05, $hash_intermediate_00{$iii_003 - 1} );
115             }
116             Readonly my %DAY_OF_WEEK_ON_FIRST_OF_YEAR => %hash_intermediate_00;
117              
118              
119             # Create READ ONLY hash to hold day of week on each first of month for each year phase
120             my %hash_intermediate_01;
121             for ( my $iii_007=0; $iii_007<$NUMBER_OF_YEAR_PHASES; $iii_007++ )
122             {
123             $hash_intermediate_01{$iii_007}{1} = get_first_of_month_day_of_week( 1, $iii_007 );
124             $hash_intermediate_01{$iii_007}{2} = get_first_of_month_day_of_week( 2, $iii_007 );
125             $hash_intermediate_01{$iii_007}{3} = get_first_of_month_day_of_week( 3, $iii_007 );
126             $hash_intermediate_01{$iii_007}{4} = get_first_of_month_day_of_week( 4, $iii_007 );
127             $hash_intermediate_01{$iii_007}{5} = get_first_of_month_day_of_week( 5, $iii_007 );
128             $hash_intermediate_01{$iii_007}{6} = get_first_of_month_day_of_week( 6, $iii_007 );
129             $hash_intermediate_01{$iii_007}{7} = get_first_of_month_day_of_week( 7, $iii_007 );
130             $hash_intermediate_01{$iii_007}{8} = get_first_of_month_day_of_week( 8, $iii_007 );
131             $hash_intermediate_01{$iii_007}{9} = get_first_of_month_day_of_week( 9, $iii_007 );
132             $hash_intermediate_01{$iii_007}{10} = get_first_of_month_day_of_week( 10, $iii_007 );
133             $hash_intermediate_01{$iii_007}{11} = get_first_of_month_day_of_week( 11, $iii_007 );
134             $hash_intermediate_01{$iii_007}{12} = get_first_of_month_day_of_week( 12, $iii_007 );
135             }
136              
137             Readonly my %NUMERIC_DAY_OF_WEEK_ON_FIRST_OF_MONTH => %hash_intermediate_01;
138              
139              
140             # Preloaded methods go here.
141              
142             ###############################################################################
143             # Usage : date_only_parse( SCALAR )
144             # Purpose : converts variety of date strings into components for processing
145             # Returns : - if parse is successful it returns a list:
146             # : (
147             # : month_integer<1-12>,
148             # : day_of_month_integer<1-N>,
149             # : year_integer,
150             # : numeric_day_of_week<1 for Mon ... 7 for Sun>
151             # : )
152             # : - '' otherwise
153             # Parameters : text string containing date in various formats
154             # Throws : Throws exception for any invalid input
155             # Comments : Handles all years, even negative years (aka BC)
156             # : Formats Parsed
157             # : - 'month_num/day_num/year'
158             # : - 'Mon Sep 17 08:50:51 2007'
159             # : - 'September 17, 2007'
160             # : - '17 September, 2007'
161             # : - 'YYYY-MM-DD' (ex: 2007-09-01 )
162             # See Also : N/A
163             ###############################################################################
164             sub date_only_parse
165             {
166             my (
167 7509     7509 1 39970 $date_string_in_00,
168             )
169             = @_;
170              
171              
172             # Incoming Inspection
173 7509         9907 my $num_input_params_03 = 1;
174 7509 100       20287 ( @_ == $num_input_params_03 ) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_03 parameter(s), a date string in any format. '@_'.\n\n\n";
  2         250  
175 7507 100       21489 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string '$_[0]'.\n\n\n";
  2         272  
176 7505 100       18214 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$_[0]'.\n\n\n";
  1         231  
177              
178              
179 7504         14785 foreach ($date_string_in_00)
180             {
181             SWITCH:
182             {
183 7504 100 100     9231 if ( ( /^(\d{1,2})\/(\d{1,2})\/(\-{0,1}\d{1,})$/ ) && ( is_valid_date( $1, $2, $3 ) ) ) { return ( int($1), int($2), $3, get_numeric_day_of_week( $1, $2, $3 ) ); last SWITCH; } # 'month_num/day_num/year'
  7504         58025  
  6821         31206  
  0         0  
184 683 100 100     4809 if ( ( /^([a-z]{3,3})\s+([a-z]{3,3})\s+(\d{1,2})\s+\d\d:\d\d:\d\d\s+(\-{0,1}\d{1,})$/i ) && ( is_valid_date( $2, $3, $4, $1 ) ) ) { return ( set_month_to_month_number($2), $3, $4, get_numeric_day_of_week( $2, $3, $4 ) ); last SWITCH; } # 'Mon Sep 17 08:50:51 2007'
  582         1399  
  0         0  
185 101 100 100     533 if ( ( /^([a-z]{3,})\s+(\d{1,2}),\s+(\-{0,1}\d{1,})$/i ) && ( is_valid_date( $1, $2, $3 ) ) ) { return ( set_month_to_month_number($1), $2, $3, get_numeric_day_of_week( $1, $2, $3 ) ); last SWITCH; } # 'September 17, 2007'
  18         46  
  0         0  
186 83 100 100     380 if ( ( /^(\d{1,2})\s+([a-z]{3,}),\s+(\-{0,1}\d{1,})$/i ) && ( is_valid_date( $2, $1, $3 ) ) ) { return ( set_month_to_month_number($2), $1, $3, get_numeric_day_of_week( $2, $1, $3 ) ); last SWITCH; } # '17 September, 2007'
  13         42  
  0         0  
187 70 100 100     327 if ( ( /^(\-{0,1}\d{1,})\-(\d{2,2})\-(\d{2,2})$/ ) && ( is_valid_date( $2, $3, $1 ) ) ) { return ( int($2), int($3), $1, get_numeric_day_of_week( $2, $3, $1 ) ); last SWITCH; } # YYYY-MM-DD (ex: 2007-09-01 )
  8         38  
  0         0  
188             # if ( ) { $whatever = 1; last SWITCH; }
189 62         331 return ( '' );
190             }
191             }
192              
193              
194             # TBD possibly add more formats
195             # Dates parsed by Date::Parse
196             # 1995:01:24T09:08:17.1823213 ISO-8601
197             # 1995-01-24T09:08:17.1823213
198             # Wed, 16 Jun 94 07:29:35 CST Comma and day name are optional
199             # Thu, 13 Oct 94 10:13:13 -0700
200             # Wed, 9 Nov 1994 09:50:32 -0500 (EST) Text in ()'s will be ignored.
201             # 21/dec/93 17:05
202             }
203              
204              
205              
206              
207             ###############################################################################
208             # Usage : Function is overloaded to accept one of three date input types
209             # : 1) Date string
210             # : is_valid_date( SCALAR )
211             # : 2) Month, dayofmonth, year
212             # : is_valid_date( SCALAR, SCALAR, SCALAR )
213             # : 3) Month, dayofmonth, year, dayofweek
214             # : is_valid_date( SCALAR, SCALAR, SCALAR, SCALAR )
215             # Purpose : checks if date is valid
216             # Returns : - '1' if date is valid
217             # : - '' otherwise
218             # Parameters : 1) ( date string in any format )
219             # : OR
220             # : 2) ( month, day of month, year )
221             # : OR
222             # : 3) ( month, day of month, year, dayofweek )
223             # Throws : No Exceptions
224             # Comments : - Handles all years, even negative years (aka BC)
225             # : - Month can be any of numeric, three character abbreviation or
226             # : full
227             # : - Day of week can be any of numeric, three character
228             # : abbreviation or full
229             # : - <1 for Jan ... 12 for Dec>
230             # : - <1 for Mon ... 7 for Sun>
231             # See Also : N/A
232             ###############################################################################
233             sub is_valid_date
234             {
235              
236              
237             # Incoming Inspection
238 7542 100 100 7542 1 46176 if ( ( @_ != 1 ) && ( @_ != 3 ) && ( @_ != 4 ) )
      100        
239             {
240 3         18 return ( '' );
241             }
242              
243              
244 7539         13361 my ( $month_input_00, $day_of_month_in_00, $year_in_00, $day_of_week_in_00 );
245 0         0 my $month_num_00;
246 7539 100       22864 if ( @_ == 1 ) # recursive and back into 'is_valid_date' one time just to get date string parsed
    100          
247             {
248 10         16 my $date_in_04 = $_[0];
249 10 100       34 if ( ref(\$date_in_04) ne 'SCALAR' )
250             {
251 1         6 return ( '' );
252             }
253              
254 9 100       23 if ( $date_in_04 eq '' )
255             {
256 1         6 return ( '' );
257             }
258              
259 8 100       18 if ( date_only_parse($date_in_04) eq '' )
260             {
261 6         33 return ( '' );
262             }
263             else
264             {
265 2         12 return ( '1' );
266             }
267             }
268             elsif ( @_ == 3 ) # day of week is NOT given by user
269             {
270 6909         33902 ( $month_input_00, $day_of_month_in_00, $year_in_00 ) = @_;
271 6909 100       29991 if ( !(is_valid_month($month_input_00)) )
272             {
273 16         82 return ( '' );
274             }
275              
276 6893 100       17064 if ( !(is_valid_year($year_in_00)) )
277             {
278 1         6 return ( '' );
279             }
280              
281 6892 100       16229 if ( !(is_valid_day_of_month($month_input_00, $day_of_month_in_00, $year_in_00)) )
282             {
283 26         206 return ( '' );
284             }
285             }
286             else # day of week IS given by user
287             {
288 620         2878 ( $month_input_00, $day_of_month_in_00, $year_in_00, $day_of_week_in_00 ) = @_;
289 620 100       1668 if ( !(is_valid_month($month_input_00)) )
290             {
291 1         5 return ( '' );
292             }
293              
294 619 100       1204 if ( !(is_valid_year($year_in_00)) )
295             {
296 1         6 return ( '' );
297             }
298              
299 618 100       1314 if ( !(is_valid_day_of_month($month_input_00, $day_of_month_in_00, $year_in_00)) )
300             {
301 4         26 return ( '' );
302             }
303              
304 614 100       1304 if ( !(is_valid_day_of_week($day_of_week_in_00)) )
305             {
306 3         18 return ( '' );
307             }
308             }
309              
310              
311             # Set to numeric forms
312 7477         14905 $month_num_00 = set_month_to_month_number($month_input_00);
313              
314 7477         20241 my $day_of_week_on_day_n_00 = get_numeric_day_of_week(
315             $month_num_00, # month in digits or alpha
316             $day_of_month_in_00, # day of month in digits
317             $year_in_00, # year in digits
318             );
319              
320             # Check calculated day of week matches the input from user
321 7477 100       15716 if ( $day_of_week_in_00 )
322             {
323 611 100       1641 if ( set_day_to_day_number($day_of_week_in_00) != $day_of_week_on_day_n_00 )
324             {
325 7         50 return ( '' );
326             }
327             }
328              
329 7470         33353 return ( '1' );
330             }
331              
332              
333              
334              
335             ###############################################################################
336             # Usage : calculate_day_of_week_for_first_of_month_in_next_year( SCALAR, SCALAR )
337             # Purpose : calculates the day of the week on the first of the month twelve months from the current month
338             # Returns : numeric day of week if successful
339             # Parameters : (
340             # : number of days between the first of the current month and the first of the month twelve months later,
341             # : alpha or numeric_day_of_week for first of current month <1 for Mon ... 7 for Sun>
342             # : )
343             # Throws : Throws exception for any invalid input
344             # Comments : N/A
345             # See Also : N/A
346             ###############################################################################
347             sub calculate_day_of_week_for_first_of_month_in_next_year
348             {
349             my (
350 18396     18396 1 38598 $num_days_in_year_02,
351             $day_of_week_on_first_of_month_00,
352             )
353             = @_;
354              
355              
356             # Incoming Inspection
357 18396         33405 my $num_input_params_15 = 2;
358 18396 100       49523 ( @_ == $num_input_params_15) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_15 parameter(s), the number of days in a calender year (either 365 or 366). '@_'.\n\n\n";
  5         590  
359 18391 100       53222 ( ref(\$num_days_in_year_02) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the number of days in a calender year (either 365 or 366) '$num_days_in_year_02'.\n\n\n";
  1         149  
360 18390 100       61866 ( $num_days_in_year_02 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the number of days in a calender year (either 365 or 366) '$num_days_in_year_02'.\n\n\n";
  1         112  
361 18389 100 100     57675 ( ( $num_days_in_year_02 eq '365' ) || ( $num_days_in_year_02 eq '366' ) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a number (1-7) for the number of days in a calender year (either 365 or 366) '$num_days_in_year_02'.\n\n\n";
  3         315  
362              
363 18386 100       49552 ( ref(\$day_of_week_on_first_of_month_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day of the week for the first of a month '$day_of_week_on_first_of_month_00'.\n\n\n";
  1         146  
364 18385 100       37857 ( $day_of_week_on_first_of_month_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the day of the week for the first of a month '$day_of_week_on_first_of_month_00'.\n\n\n";
  1         109  
365 18384 100       31166 ( is_valid_day_of_week($day_of_week_on_first_of_month_00) =~ m/^\d$/ ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a number (1-7) for the day of the week for the first of a month '$day_of_week_on_first_of_month_00'.\n\n\n";
  2         362  
366              
367 18382         35979 $day_of_week_on_first_of_month_00 = set_day_to_day_number($day_of_week_on_first_of_month_00);
368              
369              
370 18382         49561 $day_of_week_on_first_of_month_00 += ($num_days_in_year_02) % 7;
371 18382 100       35573 if ( $day_of_week_on_first_of_month_00 > 7 )
372             {
373 3271         4144 $day_of_week_on_first_of_month_00 -= 7;
374             }
375              
376 18382         146179 return ( $day_of_week_on_first_of_month_00 );
377             }
378              
379              
380              
381              
382             ###############################################################################
383             # Usage : is_leap_year( SCALAR )
384             # Purpose : determine if year is a leap year or not
385             # Returns : - 'yes' if the input is a leap year
386             # : - '' if the input is a NON leap year
387             # Parameters : (
388             # : year in integer form
389             # : )
390             # Throws : Throws exception for any invalid input
391             # Comments : Handles all years, even negative years (aka BC)
392             # See Also : N/A
393             ###############################################################################
394             sub is_leap_year
395             {
396             my (
397 372398     372398 1 588527 $year_in_01,
398             )
399             = @_;
400              
401              
402             # Incoming Inspection
403 372398         450751 my $num_input_params_01 = 1;
404 372398 100       879539 ( @_ == $num_input_params_01) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a year number. '@_'.\n\n\n";
  2         345  
405 372396 100       930009 ( ref(\$year_in_01) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year '$year_in_01'.\n\n\n";
  2         254  
406 372394 100       814802 ( $year_in_01 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the year '$year_in_01'.\n\n\n";
  1         128  
407 372393 100       1331119 ( $year_in_01 =~ m/^\-{0,1}\d+$/ ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a number for the year '$year_in_01'.\n\n\n";
  3         401  
408              
409              
410 372390         508171 my $leap_year_status_01 = 'yes';
411 372390 100       873841 if ( $year_in_01 % 4 > 0 )
412             {
413 277880         407356 $leap_year_status_01 = '';
414             }
415 372390 100 100     1011372 if ( ( $year_in_01 % 100 == 0 ) && ( $year_in_01 % 400 > 0 ) )
416             {
417 2869         4678 $leap_year_status_01 = '';
418             }
419              
420 372390         1082032 return ( $leap_year_status_01 );
421             }
422              
423              
424              
425              
426             ###############################################################################
427             # Usage : get_year_phase( SCALAR )
428             # Purpose : determine the phase of the current year within the standard 400 year cycle
429             # Returns : - year phase (0-399) for the given year if input is valid
430             # Parameters : (
431             # : year in integer form
432             # : )
433             # Throws : Throws exception for any invalid input
434             # Comments : - Handles all years, even negative years (aka BC)
435             # : - years repeat in a standard 400 year cycle where year 2000 is defined by this program to be phase '0' and year 2399 is then phase '399'
436             # : - examples: years -1, 399 and 1999 are all phase 399
437             # : years -400, 0, 1600 and 2000 are all phase 0
438             # : year 1946 is phase 346
439             # See Also : N/A
440             ###############################################################################
441             sub get_year_phase
442             {
443             my (
444 236253     236253 1 379061 $year_in_02,
445             )
446             = @_;
447              
448              
449             # Incoming Inspection
450 236253         287829 my $num_input_params_02 = 1;
451 236253 100       503485 ( @_ == $num_input_params_02) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a year number. '@_'.\n\n\n";
  1         214  
452 236252 100       568100 ( ref(\$year_in_02) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year '$year_in_02'.\n\n\n";
  2         308  
453 236250 100       569517 ( $year_in_02 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the year '$year_in_02'.\n\n\n";
  1         215  
454 236249 100       822761 ( $year_in_02 =~ m/^\-{0,1}\d+$/ ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a number for the year '$year_in_02'.\n\n\n";
  3         524  
455              
456 236246         890551 my $year_offset_00 = $year_in_02 - $DATE_BASELINE_YEAR_2000;
457 236246         1341425 my $year_phase_00;
458              
459 236246 100       678716 if ( $year_offset_00 > 0 )
    100          
460             {
461 3388         8684 $year_phase_00 = $year_offset_00 % $NUMBER_OF_YEAR_PHASES;
462             }
463             elsif ( $year_offset_00 < 0 )
464             {
465 231173         727539 $year_phase_00 = $NUMBER_OF_YEAR_PHASES - ( (-$year_offset_00) % $NUMBER_OF_YEAR_PHASES);
466 231173 100       1902041 if ( $year_phase_00 == 400 )
467             {
468 2740         5929 $year_phase_00 = '0';
469             }
470             }
471             else
472             {
473 1685         3111 $year_phase_00 = '';
474             }
475              
476 236246 100       551184 if ( $year_phase_00 eq '')
477             {
478 1685         2749 $year_phase_00 = '0';
479             }
480              
481 236246         564416 return ( $year_phase_00 );
482             }
483              
484              
485              
486              
487             ###############################################################################
488             # Usage : number_of_day_within_year( SCALAR )
489             # Purpose : get the day number within the year
490             # Returns : integer day number if successful
491             # Parameters : (
492             # : text string containing date in various formats which are parsed
493             # : )
494             # Throws : Throws exception for any invalid input
495             # Comments : Jan 31 ALWAYS returns '31' and Dec 31 returns either '365' or '366' depending upon leap year
496             # See Also : N/A
497             ###############################################################################
498             sub number_of_day_within_year
499             {
500             my (
501 2288     2288 1 13855 $date_in_00,
502             )
503             = @_;
504              
505              
506             # Incoming Inspection
507 2288         4468 my $num_input_params_00 = 1;
508 2288 100       7770 ( @_ == $num_input_params_00) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a date string. '@_'.\n\n\n";
  2         452  
509 2286 100       15604 ( ref(\$date_in_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string '$date_in_00'.\n\n\n";
  2         255  
510 2284 100       7122 ( $date_in_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$date_in_00'.\n\n\n";
  1         131  
511 2283 100       6311 ( date_only_parse($date_in_00) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date string '$date_in_00'.\n\n\n";
  5         637  
512              
513 2278         8014 my ( $month_num_01, $day_of_month_01, $year_num_01, $day_of_week_01 ) = date_only_parse($date_in_00);
514              
515 2278         7650 my $month_num_05 = set_month_to_month_number($month_num_01);
516              
517              
518 2278         4134 my $number_of_day_in_year = $day_of_month_01;
519 2278         6802 for ( my $iii_001=0; $iii_001<($month_num_05-1); $iii_001++ )
520             {
521 13163 100       28087 if ( $iii_001 == 1 )
522             {
523 1912 100       5596 if ( is_leap_year($year_num_01) )
524             {
525 687         1954 $number_of_day_in_year += get_number_of_days_in_month($iii_001+1, $year_num_01);
526             }
527             else
528             {
529 1225         3047 $number_of_day_in_year += get_number_of_days_in_month($iii_001+1, $year_num_01);
530             }
531             }
532             else
533             {
534 11251         27233 $number_of_day_in_year += get_number_of_days_in_month($iii_001+1, $year_num_01);
535             }
536             }
537              
538 2278         18281 return ( $number_of_day_in_year ) ;
539             }
540              
541              
542              
543              
544             ###############################################################################
545             # Usage : month_name_to_month_number( SCALAR )
546             # Purpose : convert alpha month name to month number
547             # Returns : integer month number (1-12) if successful
548             # Parameters : full or three character abbreviated month name
549             # Throws : Throws exception for any invalid input
550             # Comments : N/A
551             # See Also : N/A
552             ###############################################################################
553             sub month_name_to_month_number
554             {
555             my (
556 283530     283530 1 440353 $month_in_02,
557             )
558             = @_;
559              
560              
561             # Incoming Inspection
562 283530         344562 my $num_input_params_14 = 1;
563 283530 100       604314 ( @_ == $num_input_params_14) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_14 parameter(s), a month string. '@_'.\n\n\n";
  1         166  
564 283529 100       647575 ( ref(\$month_in_02) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month string '$month_in_02'.\n\n\n";
  2         275  
565 283527 100       625269 ( $month_in_02 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the month string '$month_in_02'.\n\n\n";
  1         131  
566              
567              
568             # Check for expected strings
569 283526 100       549042 ( is_valid_month($month_in_02) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the month from the input month string '$month_in_02'.\n\n\n";
  3         443  
570 283523         722998 $month_in_02 =~ m/^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December)$/i;
571              
572              
573 283523         839439 foreach ( uc($1) )
574             {
575             SWITCH:
576             {
577 283523 100       336878 if ( /^(JAN|JANUARY)$/ ) { return ( 1 ); last SWITCH; }
  283523         702443  
  25870         70775  
  0         0  
578 257653 100       581807 if ( /^(FEB|FEBRUARY)$/ ) { return ( 2 ); last SWITCH; }
  23705         65141  
  0         0  
579 233948 100       542550 if ( /^(MAR|MARCH)$/ ) { return ( 3 ); last SWITCH; }
  22747         102757  
  0         0  
580 211201 100       483291 if ( /^(APR|APRIL)$/ ) { return ( 4 ); last SWITCH; }
  22433         67779  
  0         0  
581 188768 100       474464 if ( /^(MAY|MAY)$/ ) { return ( 5 ); last SWITCH; }
  22056         68351  
  0         0  
582 166712 100       390213 if ( /^(JUN|JUNE)$/ ) { return ( 6 ); last SWITCH; }
  21960         63145  
  0         0  
583 144752 100       333513 if ( /^(JUL|JULY)$/ ) { return ( 7 ); last SWITCH; }
  31190         105453  
  0         0  
584 113562 100       253467 if ( /^(AUG|AUGUST)$/ ) { return ( 8 ); last SWITCH; }
  21371         60273  
  0         0  
585 92191 100       218804 if ( /^(SEP|SEPTEMBER)$/ ) { return ( 9 ); last SWITCH; }
  21263         62937  
  0         0  
586 70928 100       206297 if ( /^(OCT|OCTOBER)$/ ) { return ( 10 ); last SWITCH; }
  23923         68197  
  0         0  
587 47005 100       128373 if ( /^(NOV|NOVEMBER)$/ ) { return ( 11 ); last SWITCH; }
  21166         61317  
  0         0  
588 25839 100       96535 if ( /^(DEC|DECEMBER)$/ ) { return ( 12 ); last SWITCH; }
  25838         82029  
  0         0  
589 1         5 croak "\n\n ($0) '${\(caller(0))[3]}' This month of year condition, '$month_in_02', must be in alpha form. Something is amiss.\n\n\n";
  1         144  
590             }
591             }
592             }
593              
594              
595              
596              
597             ###############################################################################
598             # Usage : day_name_to_day_number( SCALAR )
599             # Purpose : convert alpha day of week name to day of week number
600             # Returns : integer day of week number (1-7) if successful
601             # Parameters : full or three character abbreviated day of week name
602             # Throws : Throws exception for any invalid input
603             # Comments : <1 for Mon ... 7 for Sun>
604             # See Also : N/A
605             ###############################################################################
606             sub day_name_to_day_number
607             {
608             my (
609 239884     239884 1 356664 $day_in_02,
610             )
611             = @_;
612              
613              
614             # Incoming Inspection
615 239884         324140 my $num_input_params_05 = 1;
616 239884 100       552913 ( @_ == $num_input_params_05) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a day string. '@_'.\n\n\n";
  1         164  
617 239883 100       8612996 ( ref(\$day_in_02) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day string '$day_in_02'.\n\n\n";
  2         301  
618 239881 100       530781 ( $day_in_02 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the day string '$day_in_02'.\n\n\n";
  1         131  
619              
620              
621             # Check for expected strings
622 239880 100       496246 ( is_valid_day_of_week($day_in_02) ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the day from the input day string '$day_in_02'.\n\n\n";
  5         815  
623 239875         771467 $day_in_02 =~ m/^(\d|Mon|Tue|Wed|Thu|Fri|Sat|Sun|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)$/i;
624              
625 239875         6968873 foreach ( uc($1) )
626             {
627             SWITCH:
628             {
629 239875 100       299366 if ( /^(MON|MONDAY)$/ ) { return ( 1 ); last SWITCH; }
  239875         598956  
  33626         143325  
  0         0  
630 206249 100       495444 if ( /^(TUE|TUESDAY)$/ ) { return ( 2 ); last SWITCH; }
  34801         113332  
  0         0  
631 171448 100       406318 if ( /^(WED|WEDNESDAY)$/ ) { return ( 3 ); last SWITCH; }
  34178         97086  
  0         0  
632 137270 100       319610 if ( /^(THU|THURSDAY)$/ ) { return ( 4 ); last SWITCH; }
  34173         89598  
  0         0  
633 103097 100       258423 if ( /^(FRI|FRIDAY)$/ ) { return ( 5 ); last SWITCH; }
  34808         112203  
  0         0  
634 68289 100       195347 if ( /^(SAT|SATURDAY)$/ ) { return ( 6 ); last SWITCH; }
  33569         103125  
  0         0  
635 34720 100       136395 if ( /^(SUN|SUNDAY)$/ ) { return ( 7 ); last SWITCH; }
  34719         113433  
  0         0  
636 1         4 croak "\n\n ($0) '${\(caller(0))[3]}' This day of week value, '$day_in_02', should not occur. Something is amiss.\n\n\n";
  1         139  
637             }
638             }
639             }
640              
641              
642              
643              
644             ###############################################################################
645             # Usage : month_number_to_month_name( SCALAR )
646             # Purpose : convert month number to month alpha
647             # Returns : three character abbreviated month name if successful
648             # Parameters : month number (1-12)
649             # Throws : Throws exception for any invalid input
650             # Comments : N/A
651             # See Also : N/A
652             ###############################################################################
653             sub month_number_to_month_name
654             {
655             my (
656 280242     280242 1 398825 $month_in_03,
657             )
658             = @_;
659              
660              
661             # Incoming Inspection
662 280242         353991 my $num_input_params_06 = 1;
663 280242 100       608606 ( @_ == $num_input_params_06) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a month number. '@_'.\n\n\n";
  1         209  
664 280241 100       735031 ( ref(\$month_in_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month number '$month_in_03'.\n\n\n";
  2         274  
665 280239 100       565429 ( $month_in_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the month number '$month_in_03'.\n\n\n";
  1         140  
666              
667             # Check for expected strings
668 280238 100       941650 ( $month_in_03 =~ m/^(\d{1,2})$/i ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the month from the input month number '$month_in_03'.\n\n\n";
  4         573  
669              
670              
671 280234         493786 foreach ($1)
672             {
673             SWITCH:
674             {
675 280234 100       318387 if ( $_ == 1 ) { return ( 'Jan' ); last SWITCH; }
  280234         784916  
  25339         74329  
  0         0  
676 254895 100       598070 if ( $_ == 2 ) { return ( 'Feb' ); last SWITCH; }
  23412         90198  
  0         0  
677 231483 100       583148 if ( $_ == 3 ) { return ( 'Mar' ); last SWITCH; }
  22723         78637  
  0         0  
678 208760 100       504572 if ( $_ == 4 ) { return ( 'Apr' ); last SWITCH; }
  22414         76384  
  0         0  
679 186346 100       423771 if ( $_ == 5 ) { return ( 'May' ); last SWITCH; }
  21987         72838  
  0         0  
680 164359 100       378059 if ( $_ == 6 ) { return ( 'Jun' ); last SWITCH; }
  21910         66964  
  0         0  
681 142449 100       335612 if ( $_ == 7 ) { return ( 'Jul' ); last SWITCH; }
  29184         97694  
  0         0  
682 113265 100       234435 if ( $_ == 8 ) { return ( 'Aug' ); last SWITCH; }
  21341         71437  
  0         0  
683 91924 100       216666 if ( $_ == 9 ) { return ( 'Sep' ); last SWITCH; }
  21179         67514  
  0         0  
684 70745 100       153171 if ( $_ == 10 ) { return ( 'Oct' ); last SWITCH; }
  23847         73196  
  0         0  
685 46898 100       118366 if ( $_ == 11 ) { return ( 'Nov' ); last SWITCH; }
  21143         69782  
  0         0  
686 25755 100       64421 if ( $_ == 12 ) { return ( 'Dec' ); last SWITCH; }
  25749         79958  
  0         0  
687 6         22 croak "\n\n ($0) '${\(caller(0))[3]}' This month of year value, '$month_in_03', should not occur. Something is amiss.\n\n\n";
  6         851  
688             }
689             }
690             }
691              
692              
693              
694              
695             ###############################################################################
696             # Usage : day_number_to_day_name( SCALAR )
697             # Purpose : convert day of week number to day of week alpha
698             # Returns : three character abbreviated day of week name if successful
699             # Parameters : day of week number (1-7)
700             # Throws : Throws exception for any invalid input
701             # Comments : <1 for Mon ... 7 for Sun>
702             # See Also : N/A
703             ###############################################################################
704             sub day_number_to_day_name
705             {
706             my (
707 239255     239255 1 402411 $day_in_03,
708             )
709             = @_;
710              
711              
712             # Incoming Inspection
713 239255         317984 my $num_input_params_07 = 1;
714 239255 100       553882 ( @_ == $num_input_params_07) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a day number. '@_'.\n\n\n";
  1         210  
715 239254 100       602814 ( ref(\$day_in_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day number '$day_in_03'.\n\n\n";
  2         248  
716 239252 100       556284 ( $day_in_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the day number '$day_in_03'.\n\n\n";
  1         142  
717              
718              
719             # Check for expected strings
720 239251 100       816414 ( $day_in_03 =~ m/^(\d{1,2})$/i ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the day from the input day number '$day_in_03'.\n\n\n";
  3         412  
721              
722              
723 239248         472342 foreach ($1)
724             {
725             SWITCH:
726             {
727 239248 100       305198 if ( $_ == 1 ) { return ( 'Mon' ); last SWITCH; }
  239248         685376  
  33509         99269  
  0         0  
728 205739 100       509039 if ( $_ == 2 ) { return ( 'Tue' ); last SWITCH; }
  34694         107385  
  0         0  
729 171045 100       396926 if ( $_ == 3 ) { return ( 'Wed' ); last SWITCH; }
  34096         105164  
  0         0  
730 136949 100       329906 if ( $_ == 4 ) { return ( 'Thu' ); last SWITCH; }
  34095         111380  
  0         0  
731 102854 100       239591 if ( $_ == 5 ) { return ( 'Fri' ); last SWITCH; }
  34650         127015  
  0         0  
732 68204 100       161868 if ( $_ == 6 ) { return ( 'Sat' ); last SWITCH; }
  33502         107891  
  0         0  
733 34702 100       116706 if ( $_ == 7 ) { return ( 'Sun' ); last SWITCH; }
  34696         104985  
  0         0  
734 6         22 croak "\n\n ($0) '${\(caller(0))[3]}' This day of week value, '$day_in_03', should not occur. Something is amiss.\n\n\n";
  6         866  
735             }
736             }
737             }
738              
739              
740              
741              
742             ###############################################################################
743             # Usage : set_day_to_day_name_abbrev( SCALAR )
744             # Purpose : set the incoming day of week to three letter abbreviation
745             # Returns : three character abbreviated day of week name if successful
746             # Parameters : day of week in one of three formats ( numeric<1-7>, full name or three character abbreviated )
747             # Throws : Throws exception for any invalid input
748             # Comments : <1 for Mon ... 7 for Sun>
749             # See Also : N/A
750             ###############################################################################
751             sub set_day_to_day_name_abbrev
752             {
753             my (
754 35     35 1 5715 $day_in_04,
755             )
756             = @_;
757              
758              
759             # Incoming Inspection
760 35         50 my $num_input_params_08 = 1;
761 35 100       97 ( @_ == $num_input_params_08) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a day number or day alpha. '@_'.\n\n\n";
  1         183  
762 34 100       104 ( ref(\$day_in_04) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day number or day alpha '$day_in_04'.\n\n\n";
  2         353  
763 32 100       89 ( $day_in_04 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the day number or day alpha '$day_in_04'.\n\n\n";
  1         127  
764              
765 31 100       158 if ( $day_in_04 =~ m/^(\d{1,2})$/i )
766             {
767 15         47 return ( day_number_to_day_name($day_in_04) );
768             }
769             else
770             {
771 16         34 return ( day_number_to_day_name(day_name_to_day_number($day_in_04)) );
772             }
773             }
774              
775              
776              
777              
778             ###############################################################################
779             # Usage : set_day_to_day_name_full( SCALAR )
780             # Purpose : set the incoming day of week to full name
781             # Returns : day of week FULL name if successful
782             # Parameters : day of week in one of three formats ( numeric<1-7>, full name or three character abbreviated )
783             # Throws : Throws exception for any invalid input
784             # Comments : <1 for Monday ... 7 for Sunday>
785             # See Also : N/A
786             ###############################################################################
787             sub set_day_to_day_name_full
788             {
789             my (
790 18     18 1 6080 $day_in_06,
791             )
792             = @_;
793              
794              
795             # Incoming Inspection
796 18         28 my $num_input_params_35 = 1;
797 18 100       49 ( @_ == $num_input_params_35) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly ${num_input_params_35} parameter, a day number or day alpha. '@_'.\n\n\n";
  1         202  
798 17 100       64 ( ref(\$day_in_06) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day number or day alpha '$day_in_06'.\n\n\n";
  2         260  
799 15 100       47 ( $day_in_06 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the day number or day alpha '$day_in_06'.\n\n\n";
  1         134  
800 14 100       31 ( is_valid_day_of_week($day_in_06) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid the day of the week in either alpha or numeric format '$day_in_06'.\n\n\n";
  4         633  
801              
802              
803 10         23 my $day_of_week_10 = set_day_to_day_number($day_in_06);
804 10         21 foreach ($day_of_week_10)
805             {
806             SWITCH:
807             {
808 10 100       14 if ( $_ == 1 ) { return ( 'Monday' ); last SWITCH; }
  10         54  
  1         6  
  0         0  
809 9 100       25 if ( $_ == 2 ) { return ( 'Tuesday' ); last SWITCH; }
  2         11  
  0         0  
810 7 100       21 if ( $_ == 3 ) { return ( 'Wednesday' ); last SWITCH; }
  1         5  
  0         0  
811 6 100       27 if ( $_ == 4 ) { return ( 'Thursday' ); last SWITCH; }
  1         6  
  0         0  
812 5 100       28 if ( $_ == 5 ) { return ( 'Friday' ); last SWITCH; }
  1         6  
  0         0  
813 4 100       92 if ( $_ == 6 ) { return ( 'Saturday' ); last SWITCH; }
  2         185  
  0         0  
814 2         12 return ( 'Sunday' );
815             }
816             }
817             }
818              
819              
820              
821              
822             ###############################################################################
823             # Usage : set_month_to_month_name_abbrev( SCALAR )
824             # Purpose : set the incoming month to three letter abbreviation
825             # Returns : three character abbreviated month name if successful
826             # Parameters : month in one of three formats ( numeric<1-12>, full name or three character abbreviated )
827             # Throws : Throws exception for any invalid input
828             # Comments : N/A
829             # See Also : N/A
830             ###############################################################################
831             sub set_month_to_month_name_abbrev
832             {
833             my (
834 49     49 1 5438 $month_in_04,
835             )
836             = @_;
837              
838              
839             # Incoming Inspection
840 49         64 my $num_input_params_09 = 1;
841 49 100       130 ( @_ == $num_input_params_09) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a month number or month alpha. '@_'.\n\n\n";
  1         202  
842 48 100       143 ( ref(\$month_in_04) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month number or month alpha '$month_in_04'.\n\n\n";
  2         274  
843 46 100       118 ( $month_in_04 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the month number or month alpha '$month_in_04'.\n\n\n";
  1         145  
844              
845 45 100       234 if ( $month_in_04 =~ m/^(\d{1,2})$/i )
846             {
847 20         46 return ( month_number_to_month_name($month_in_04) );
848             }
849             else
850             {
851 25         54 return ( month_number_to_month_name(month_name_to_month_number($month_in_04)) );
852             }
853             }
854              
855              
856              
857              
858             ###############################################################################
859             # Usage : set_month_to_month_name_full( SCALAR )
860             # Purpose : set the incoming month to full name
861             # Returns : month FULL name if successful
862             # Parameters : month in one of three formats ( numeric<1-12>, full name or three character abbreviated )
863             # Throws : Throws exception for any invalid input
864             # Comments : N/A
865             # See Also : N/A
866             ###############################################################################
867             sub set_month_to_month_name_full
868             {
869             my (
870 25     25 1 6410 $month_in_07,
871             )
872             = @_;
873              
874              
875             # Incoming Inspection
876 25         40 my $num_input_params_34 = 1;
877 25 100       68 ( @_ == $num_input_params_34) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly ${num_input_params_34} parameter, a month number or month alpha. '@_'.\n\n\n";
  1         193  
878 24 100       72 ( ref(\$month_in_07) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month number or month alpha '$month_in_07'.\n\n\n";
  2         259  
879 22 100       65 ( $month_in_07 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the month number or month alpha '$month_in_07'.\n\n\n";
  1         135  
880 21 100       49 ( is_valid_month($month_in_07) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the month from the input month string '$month_in_07'.\n\n\n";
  5         805  
881              
882              
883 16         34 my $month_num_15 = set_month_to_month_number($month_in_07);
884 16         33 foreach ($month_num_15)
885             {
886             SWITCH:
887             {
888 16 100       20 if ( $_ == 1 ) { return ( 'January' ); last SWITCH; }
  16         35  
  1         6  
  0         0  
889 15 100       30 if ( $_ == 2 ) { return ( 'February' ); last SWITCH; }
  3         12  
  0         0  
890 12 100       26 if ( $_ == 3 ) { return ( 'March' ); last SWITCH; }
  1         5  
  0         0  
891 11 100       21 if ( $_ == 4 ) { return ( 'April' ); last SWITCH; }
  2         10  
  0         0  
892 9 100       20 if ( $_ == 5 ) { return ( 'May' ); last SWITCH; }
  1         7  
  0         0  
893 8 100       18 if ( $_ == 6 ) { return ( 'June' ); last SWITCH; }
  1         6  
  0         0  
894 7 100       13 if ( $_ == 7 ) { return ( 'July' ); last SWITCH; }
  1         5  
  0         0  
895 6 100       14 if ( $_ == 8 ) { return ( 'August' ); last SWITCH; }
  2         11  
  0         0  
896 4 100       11 if ( $_ == 9 ) { return ( 'September' ); last SWITCH; }
  1         6  
  0         0  
897 3 100       7 if ( $_ == 10 ) { return ( 'October' ); last SWITCH; }
  1         5  
  0         0  
898 2 100       7 if ( $_ == 11 ) { return ( 'November' ); last SWITCH; }
  1         5  
  0         0  
899 1         6 return ( 'December' );
900             }
901             }
902             }
903              
904              
905              
906              
907             ###############################################################################
908             # Usage : set_day_to_day_number( SCALAR )
909             # Purpose : set the incoming day of week to day of week number
910             # Returns : numeric<1-7> if successful
911             # Parameters : day of week in one of three formats ( numeric<1-7>, full name or three character abbreviated )
912             # Throws : Throws exception for any invalid input
913             # Comments : <1 for Mon ... 7 for Sun>
914             # See Also : N/A
915             ###############################################################################
916             sub set_day_to_day_number
917             {
918             my (
919 239854     239854 1 735470 $day_in_05,
920             )
921             = @_;
922              
923              
924             # Incoming Inspection
925 239854         1300304 my $num_input_params_10 = 1;
926 239854 100       631223 ( @_ == $num_input_params_10) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a day number or day alpha. '@_'.\n\n\n";
  1         198  
927 239853 100       636853 ( ref(\$day_in_05) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day number or day alpha '$day_in_05'.\n\n\n";
  2         301  
928 239851 100       623319 ( $day_in_05 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the day number or day alpha '$day_in_05'.\n\n\n";
  1         137  
929              
930 239850 100       817961 if ( !( $day_in_05 =~ m/^(\d{1,2})$/i ) )
931             {
932 640         1348 return ( day_name_to_day_number($day_in_05) );
933             }
934             else
935             {
936 239210         484705 return ( day_name_to_day_number(day_number_to_day_name($day_in_05)) );
937             }
938             }
939              
940              
941              
942              
943             ###############################################################################
944             # Usage : set_month_to_month_number( SCALAR )
945             # Purpose : set the incoming month to month number
946             # Returns : numeric month <1-12> if successful
947             # Parameters : month in one of three formats ( numeric<1-12>, full name or three character abbreviated )
948             # Throws : Throws exception for any invalid input
949             # Comments : N/A
950             # See Also : N/A
951             ###############################################################################
952             sub set_month_to_month_number
953             {
954             my (
955 283481     283481 1 461076 $month_in_06,
956             )
957             = @_;
958              
959              
960             # Incoming Inspection
961 283481         372010 my $num_input_params_11 = 1;
962 283481 100       654467 ( @_ == $num_input_params_11) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a month number or month alpha. '@_'.\n\n\n";
  1         189  
963 283480 100       711313 ( ref(\$month_in_06) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month number or month alpha '$month_in_06'.\n\n\n";
  2         238  
964 283478 100       621622 ( $month_in_06 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the month number or month alpha '$month_in_06'.\n\n\n";
  1         128  
965              
966 283477 100       891099 if ( !( $month_in_06 =~ m/^(\d{1,2})$/i ) )
967             {
968 3301         6171 return ( month_name_to_month_number($month_in_06) );
969             }
970             else
971             {
972 280176         599261 return ( month_name_to_month_number(month_number_to_month_name($month_in_06)) );
973             }
974             }
975              
976              
977              
978              
979             ###############################################################################
980             # Usage : get_num_days_in_year( SCALAR )
981             # Purpose : determine number of days in given year
982             # Returns : - '366' if the input is a leap year
983             # : - '365' if the input is a NON leap year
984             # Parameters : (
985             # : year in integer form
986             # : )
987             # Throws : Throws exception for any invalid input
988             # Comments : Handles all years, even negative years (aka BC)
989             # See Also : N/A
990             ###############################################################################
991             sub get_num_days_in_year
992             {
993             my (
994 144159     144159 1 187418 $year_in_03,
995             )
996             = @_;
997              
998              
999             # Incoming Inspection
1000 144159         196312 my $num_input_params_04 = 1;
1001 144159 100       320931 ( @_ == $num_input_params_04) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly one parameter, a year number. '@_'.\n\n\n";
  1         206  
1002 144158 100       368115 ( ref(\$year_in_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year '$year_in_03'.\n\n\n";
  2         262  
1003 144156 100       345552 ( $year_in_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the year '$year_in_03'.\n\n\n";
  1         135  
1004 144155 100       490575 ( $year_in_03 =~ m/^\-{0,1}\d+$/ ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a number for the year '$year_in_03'.\n\n\n";
  3         4574  
1005              
1006 144152 100       264982 if ( is_leap_year($year_in_03) ne '' )
1007             {
1008 35135         111128 return ( 366 );
1009             }
1010             else
1011             {
1012 109017         313098 return ( 365 );
1013             }
1014             }
1015              
1016              
1017              
1018              
1019             ###############################################################################
1020             # Usage : date1_to_date2_delta( SCALAR, SCALAR )
1021             # Purpose : finds the difference in days between the two dates by subtracting the second from the first
1022             # Returns : integer day count if successful
1023             # Parameters : (
1024             # : date ONE in any format,
1025             # : date TWO in any format
1026             # : )
1027             # Throws : Throws exception for any invalid input
1028             # Comments : if day ONE is EARLIER than date TWO, a negative number is returned
1029             # See Also : N/A
1030             ###############################################################################
1031             sub date1_to_date2_delta
1032             {
1033             my (
1034 143     143 1 9274 $date_one_00,
1035             $date_two_00
1036             )
1037             = @_;
1038              
1039              
1040             # Incoming Inspection
1041 143         278 my $num_input_params_12 = 2;
1042 143 100       504 ( @_ == $num_input_params_12) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_12 parameters ('date1' and date2). '@_'.\n\n\n";
  8         1260  
1043              
1044 135 100       817 ( ref(\$date_one_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR first parameter for the first date '$date_one_00'.\n\n\n";
  1         148  
1045 134 100       520 ( ref(\$date_two_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR second parameter for the second date '$date_two_00'.\n\n\n";
  1         141  
1046              
1047 133 100       553 ( $date_one_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the first date '$date_one_00'.\n\n\n";
  1         141  
1048 132 100       343 ( $date_two_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the second date '$date_two_00'.\n\n\n";
  1         218  
1049              
1050 131 100       358 ( date_only_parse($date_one_00) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date1 string '$date_one_00'.\n\n\n";
  1         147  
1051 130 100       561 ( date_only_parse($date_two_00) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date2 string '$date_two_00'.\n\n\n";
  1         158  
1052              
1053 129         275 my $date_one_02;
1054             my $date_two_02;
1055 129         492 my $date_compare_00 = compare_date1_and_date2($date_one_00, $date_two_00);
1056              
1057 129 50 100     998 if ( ( $date_compare_00 ne '0' ) && ( $date_compare_00 ne '-1' ) && ( $date_compare_00 ne '1' ) )
      66        
1058             {
1059 0         0 croak "\n\n ($0) '${\(caller(0))[3]}' This condition should NOT occur. date_compare_00 has a value of '$date_compare_00' and only one of '1', '-1' or '0' is expected.\n\n\n";
  0         0  
1060             }
1061              
1062              
1063 129 100       308 if ( $date_compare_00 eq '0' )
1064             {
1065 4         23 return ('0');
1066             }
1067 125 100       386 if ( $date_compare_00 eq '-1' )
1068             {
1069 57         95 $date_one_02 = $date_two_00;
1070 57         86 $date_two_02 = $date_one_00;
1071             }
1072 125 100       300 if ( $date_compare_00 eq '1' )
1073             {
1074 68         103 $date_one_02 = $date_one_00;
1075 68         103 $date_two_02 = $date_two_00;
1076             }
1077              
1078              
1079 125         288 my ( $date1_month_num_02, $date1_day_of_month_02, $date1_year_num_02, $date1_day_of_week_02 ) = date_only_parse($date_one_02);
1080 125         391 my ( $date2_month_num_02, $date2_day_of_month_02, $date2_year_num_02, $date2_day_of_week_02 ) = date_only_parse($date_two_02);
1081              
1082              
1083 125         322 my $year_phase_date_one_00;
1084             my $which_400yr_cycle_occurrence_for_date_one_02;
1085 125 100       653 if ( $date1_year_num_02 >= 0 )
1086             {
1087 108         417 $which_400yr_cycle_occurrence_for_date_one_02 = int( $date1_year_num_02 / $NUMBER_OF_YEAR_PHASES );
1088 108         783 $year_phase_date_one_00 = get_year_phase( $date1_year_num_02 );
1089             }
1090             else
1091             {
1092 17         109 $which_400yr_cycle_occurrence_for_date_one_02 = int( ($date1_year_num_02+1) / $NUMBER_OF_YEAR_PHASES ) - 1;
1093 17         127 $year_phase_date_one_00 = $NUMBER_OF_YEAR_PHASES - ( -$date1_year_num_02 % $NUMBER_OF_YEAR_PHASES );
1094 17 100       132 if ( $year_phase_date_one_00 >= $NUMBER_OF_YEAR_PHASES )
1095             {
1096 2         17 $year_phase_date_one_00 -= $NUMBER_OF_YEAR_PHASES;
1097             }
1098             }
1099              
1100 125         332 my $year_phase_date_two;
1101             my $which_400yr_cycle_occurrence_for_date_two_02;
1102 125 100       333 if ( $date2_year_num_02 >= 0 )
1103             {
1104 81         237 $which_400yr_cycle_occurrence_for_date_two_02 = int( $date2_year_num_02 / $NUMBER_OF_YEAR_PHASES );
1105 81         444 $year_phase_date_two = get_year_phase( $date2_year_num_02 );
1106             }
1107             else
1108             {
1109 44         160 $which_400yr_cycle_occurrence_for_date_two_02 = int( ($date2_year_num_02+1) / $NUMBER_OF_YEAR_PHASES ) - 1;
1110 44         266 $year_phase_date_two = $NUMBER_OF_YEAR_PHASES - ( -$date2_year_num_02 % $NUMBER_OF_YEAR_PHASES );
1111 44 100       314 if ( $year_phase_date_two >= $NUMBER_OF_YEAR_PHASES )
1112             {
1113 6         39 $year_phase_date_two -= $NUMBER_OF_YEAR_PHASES;
1114             }
1115             }
1116              
1117              
1118 125         461 my $num_days_in_year1_phases_00 = 0;
1119 125         406 for ( my $iii_005=0; $iii_005<$year_phase_date_one_00; $iii_005++ )
1120             {
1121 16184         33075 $num_days_in_year1_phases_00 += get_num_days_in_year( 2000 + $iii_005 ); # sum the days of whole years
1122             }
1123 125         372 $num_days_in_year1_phases_00 += number_of_day_within_year( $date_one_02 ); # sum the days of the year up to the given day
1124              
1125              
1126 125         222 my $num_days_in_year2_phases = 0;
1127 125         423 for ( my $iii_006=0; $iii_006<$year_phase_date_two; $iii_006++ )
1128             {
1129 16766         39405 $num_days_in_year2_phases += get_num_days_in_year( 2000 + $iii_006 ); # sum the days of whole years
1130             }
1131 125         361 $num_days_in_year2_phases += number_of_day_within_year( $date_two_02 ); # sum the days of the year up to the given day
1132              
1133              
1134 125         265 my $date_diff_00 = '';
1135 125 100       397 if ( $which_400yr_cycle_occurrence_for_date_one_02 == $which_400yr_cycle_occurrence_for_date_two_02 )
    100          
1136             {
1137 70         115 $date_diff_00 = $num_days_in_year1_phases_00 - $num_days_in_year2_phases;
1138             }
1139             elsif ( $which_400yr_cycle_occurrence_for_date_one_02 == ( $which_400yr_cycle_occurrence_for_date_two_02 + 1 ) )
1140             {
1141 22         108 $date_diff_00 = $num_days_in_year1_phases_00 + ( $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE - $num_days_in_year2_phases );
1142             }
1143             # elsif ( $which_400yr_cycle_occurrence_for_date_one_02 > ( $which_400yr_cycle_occurrence_for_date_two_02 + 1 ) )
1144             else
1145             {
1146 33         350 $date_diff_00 = ($which_400yr_cycle_occurrence_for_date_one_02 - ($which_400yr_cycle_occurrence_for_date_two_02 + 1 )) * ( $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE);
1147 33         231 $date_diff_00 += $num_days_in_year1_phases_00 + ( $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE - $num_days_in_year2_phases );
1148             }
1149              
1150              
1151 125 100       590 if ( $date_compare_00 == 1 )
1152             {
1153 68         641 return ( $date_diff_00 );
1154             }
1155             else
1156             {
1157 57         541 return ( -$date_diff_00 );
1158             }
1159             }
1160              
1161              
1162              
1163              
1164             ###############################################################################
1165             # Usage : is_valid_month( SCALAR )
1166             # Purpose : checks if month is valid
1167             # Returns : - '1' if month is valid
1168             # : - '' otherwise
1169             # Parameters : (
1170             # : alpha or month integer<1-12>,
1171             # : )
1172             # Throws : No Exceptions
1173             # Comments : N/A
1174             # See Also : N/A
1175             ###############################################################################
1176             sub is_valid_month
1177             {
1178             my (
1179 563575     563575 1 858460 $month_input_01,
1180             )
1181             = @_;
1182              
1183              
1184             # Incoming Inspection
1185 563575 100       1233584 if ( @_ != 1 )
1186             {
1187 2         10 return ( '' );
1188             }
1189              
1190 563573 100       1397754 if ( ref(\$month_input_01) ne 'SCALAR' )
1191             {
1192 2         8 return ( '' );
1193             }
1194              
1195 563571 100       1223524 if ( $month_input_01 eq '' )
1196             {
1197 1         5 return ( '' );
1198             }
1199              
1200              
1201             # Check for expected strings
1202 563570 100       2156517 if ( !( $month_input_01 =~ m/^(\d{1,2}|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec|January|February|March|April|May|June|July|August|September|October|November|December)$/i ) )
1203             {
1204 51         256 return ( '' );
1205             }
1206              
1207              
1208             # Check numeric form of Month of Year for acceptable value
1209 563519 100       1625387 if ( $month_input_01 =~ m/^(\d{1,2})$/ )
1210             {
1211 277238 100 100     1652890 if ( ( $1 < 1 ) || ( $1 > 12 ) )
1212             {
1213 33         166 return ( '' );
1214             }
1215             }
1216              
1217 563486         1581512 return ( 1 );
1218             }
1219              
1220              
1221              
1222              
1223             ###############################################################################
1224             # Usage : is_valid_day_of_month( SCALAR, SCALAR, SCALAR )
1225             # Purpose : checks if day of month is valid
1226             # Returns : - '1' if day of month is valid
1227             # : - '' otherwise
1228             # Parameters : (
1229             # : alpha or month integer<1-12>,
1230             # : day of month integer<1-N>,
1231             # : year integer,
1232             # : )
1233             # Throws : No Exceptions
1234             # Comments : Handles all years, even negative years (aka BC)
1235             # See Also : N/A
1236             ###############################################################################
1237             sub is_valid_day_of_month
1238             {
1239             my (
1240 22981     22981 1 53451 $month_input_02,
1241             $day_of_month_input_00,
1242             $year_input_01,
1243             )
1244             = @_;
1245              
1246              
1247             # Incoming Inspection
1248 22981 100       47854 if ( @_ != 3 )
1249             {
1250 25         102 return ( '' );
1251             }
1252              
1253 22956 100       55127 if ( ref(\$day_of_month_input_00) ne 'SCALAR' )
1254             {
1255 1         5 return ( '' );
1256             }
1257              
1258 22955 100       46451 if ( $day_of_month_input_00 eq '' )
1259             {
1260 1         5 return ( '' );
1261             }
1262              
1263 22954 100       55886 if ( !(is_valid_month($month_input_02)) )
1264             {
1265 4         32 return ( '' );
1266             }
1267 22950         50211 my $month_num_03 = set_month_to_month_number($month_input_02);
1268              
1269 22950 100       48848 if ( !(is_valid_year($year_input_01)) )
1270             {
1271 1         5 return ( '' );
1272             }
1273              
1274              
1275 22949 100 100     221220 if ( !( ( $day_of_month_input_00 =~ m/^(\d{1,2})$/ ) && ( $1 > 0 ) && ( $1 < 32 ) ) )
      100        
1276             {
1277 52         233 return ( '' );
1278             }
1279              
1280              
1281             # Check for out of range day_of_month numbers
1282             # Months with 30 days ( April June September November )
1283 22897 100 100     188370 if ( ( ( $month_num_03 == 4 ) || ( $month_num_03 == 6 ) || ( $month_num_03 == 9 ) || ( $month_num_03 == 11 ) ) && ( $day_of_month_input_00 > 30 ) )
      100        
1284             {
1285 14         65 return ( '' );
1286             }
1287             # February (NON leap year)
1288             # elsif ( ( $month_num_03 == 2 ) && (!( is_leap_year($year_input_01) )) && ( $day_of_month_input_00 > 28 ) )
1289 22883 100 100     56732 if ( ( $month_num_03 == 2 ) && (!( is_leap_year($year_input_01) )) && ( $day_of_month_input_00 > 28 ) )
      100        
1290             {
1291 18         80 return ( '' );
1292             }
1293             # February (leap year)
1294             # elsif ( ( $month_num_03 == 2 ) && ( is_leap_year($year_input_01) ) && ( $day_of_month_input_00 > 29 ) )
1295 22865 100 100     53409 if ( ( $month_num_03 == 2 ) && ( is_leap_year($year_input_01) ) && ( $day_of_month_input_00 > 29 ) )
      100        
1296             {
1297 7         36 return ( '' );
1298             }
1299             # Months with 31 days
1300             # elsif ( ( $month_num_03 > 0 ) && ( $month_num_03 < 13 ) && ( $day_of_month_input_00 > 31 ) )
1301             # {
1302             # return ( '' );
1303             # }
1304              
1305              
1306 22858         63588 return ( 1 );
1307             }
1308              
1309              
1310              
1311              
1312             ###############################################################################
1313             # Usage : is_valid_day_of_week( SCALAR )
1314             # Purpose : checks if day of week is valid
1315             # Returns : - '1' if day of week is valid
1316             # : - '' otherwise
1317             # Parameters : (
1318             # : day of week in one of three formats ( numeric<1-7>, full name or three character abbreviated )
1319             # : )
1320             # Throws : No Exceptions
1321             # Comments : <1 for Mon ... 7 for Sun>
1322             # See Also : N/A
1323             ###############################################################################
1324             sub is_valid_day_of_week
1325             {
1326             my (
1327 258939     258939 1 345352 $day_of_week_input_00,
1328             )
1329             = @_;
1330              
1331              
1332             # Incoming Inspection
1333 258939 100       538236 if ( @_ != 1 )
1334             {
1335 2         10 return ( '' );
1336             }
1337              
1338 258937 100       628464 if ( ref(\$day_of_week_input_00) ne 'SCALAR' )
1339             {
1340 2         8 return ( '' );
1341             }
1342              
1343 258935 100       529037 if ( $day_of_week_input_00 eq '' )
1344             {
1345 1         5 return ( '' );
1346             }
1347              
1348              
1349 258934 100       936479 if ( !( $day_of_week_input_00 =~ m/^(\d|Mon|Tue|Wed|Thu|Fri|Sat|Sun|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)$/i ) )
1350             {
1351 21         118 return ( '' );
1352             }
1353              
1354              
1355             # Check numeric form of day of week for valid value
1356 258913 100       745553 if ( $day_of_week_input_00 =~ m/^(\d)$/ )
1357             {
1358 18397 100 100     127568 if ( ( $1 < 1 ) || ( $1 > 7 ) )
1359             {
1360 10         48 return ( '' );
1361             }
1362             }
1363              
1364 258903         868002 return ( 1 );
1365             }
1366              
1367              
1368              
1369              
1370             ###############################################################################
1371             # Usage : is_valid_year( SCALAR )
1372             # Purpose : checks if year is valid
1373             # Returns : - '1' if year is valid
1374             # : - '' otherwise
1375             # Parameters : (
1376             # : year in integer format
1377             # : )
1378             # Throws : No Exceptions
1379             # Comments : Handles all years, even negative years (aka BC)
1380             # See Also : N/A
1381             ###############################################################################
1382             sub is_valid_year
1383             {
1384             my (
1385 280190     280190 1 501772 $year_input_00,
1386             )
1387             = @_;
1388              
1389              
1390             # Incoming Inspection
1391 280190 100       617288 if ( @_ != 1 )
1392             {
1393 2         10 return ( '' );
1394             }
1395              
1396 280188 100       683321 if ( ref(\$year_input_00) ne 'SCALAR' )
1397             {
1398 2         10 return ( '' );
1399             }
1400              
1401 280186 100       590217 if ( $year_input_00 eq '' )
1402             {
1403 1         5 return ( '' );
1404             }
1405              
1406 280185 100       996120 if ( !( $year_input_00 =~ m/^\-{0,1}\d{1,}$/ ) )
1407             {
1408 31         166 return ( '' );
1409             }
1410              
1411 280154         776170 return ( 1 );
1412             }
1413              
1414              
1415              
1416              
1417             ###############################################################################
1418             # Usage : is_valid_400_year_cycle( SCALAR )
1419             # Purpose : checks if year is valid 400 year cycle phase number
1420             # Returns : - '1' if year is valid 400 year cycle phase number
1421             # : - '' otherwise
1422             # Parameters : (
1423             # : year in integer format
1424             # : )
1425             # Throws : No Exceptions
1426             # Comments : valid years are multiples of 400 (i.e. ... -400, 0, 400, ... 1600, 2000, 2400, ...)
1427             # See Also : N/A
1428             ###############################################################################
1429             sub is_valid_400_year_cycle
1430             {
1431             my (
1432 124     124 1 2611 $four_hundred_year_cycle_01,
1433             )
1434             = @_;
1435              
1436              
1437             # Incoming Inspection
1438 124 100       353 if ( @_ != 1 )
1439             {
1440 2         9 return ( '' );
1441             }
1442              
1443 122 100       387 if ( ref(\$four_hundred_year_cycle_01) ne 'SCALAR' )
1444             {
1445 2         10 return ( '' );
1446             }
1447              
1448 120 100       285 if ( $four_hundred_year_cycle_01 eq '' )
1449             {
1450 1         7 return ( '' );
1451             }
1452              
1453 119 100 100     961 if ( !( ( $four_hundred_year_cycle_01 =~ m/^\-{0,1}(\d+)$/ ) && ( ( $1 % $NUMBER_OF_YEAR_PHASES ) == 0 ) ) )
1454             {
1455 15         148 return ( '' );
1456             }
1457              
1458 104         884 return ( 1 );
1459             }
1460              
1461              
1462              
1463              
1464             ###############################################################################
1465             # Usage : compare_date1_and_date2( SCALAR, SCALAR )
1466             # Purpose : compares two dates to find which one is later
1467             # Returns : - '1' if the FIRST date is LATER than the second
1468             # : - '-1' if the FIRST date is EARLIER than the second
1469             # : - '0' if both dates are the same
1470             # Parameters : (
1471             # : date ONE in any format,
1472             # : date TWO in any format
1473             # : )
1474             # Throws : Throws exception for any invalid input
1475             # Comments : N/A
1476             # See Also : N/A
1477             ###############################################################################
1478             sub compare_date1_and_date2
1479             {
1480             my (
1481 158     158 1 8473 $date_one_01,
1482             $date_two_01
1483             )
1484             = @_;
1485              
1486              
1487             # Incoming Inspection
1488 158         221 my $num_input_params_18 = 2;
1489 158 100       458 ( @_ == $num_input_params_18) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_18 parameter(s), two date strings. '@_'.\n\n\n";
  7         961  
1490              
1491 151 100       534 ( ref(\$date_one_01) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the first date string '$date_one_01'.\n\n\n";
  1         129  
1492 150 100       1097 ( $date_one_01 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the first date string '$date_one_01'.\n\n\n";
  1         146  
1493 149 100       319 ( date_only_parse($date_one_01) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot parse the date from the first input date string '$date_one_01'.\n\n\n";
  1         163  
1494              
1495 148 100       513 ( ref(\$date_two_01) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the second date string '$date_two_01'.\n\n\n";
  1         196  
1496 147 100       368 ( $date_two_01 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the second date string '$date_two_01'.\n\n\n";
  1         198  
1497 146 100       325 ( date_only_parse($date_two_01) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot parse the date from the second input date string '$date_two_01'.\n\n\n";
  1         143  
1498              
1499              
1500              
1501 145         388 my ( $date1_month_num_03, $date1_day_of_month_03, $date1_year_num_03, $date1_day_of_week_03 ) = date_only_parse($date_one_01);
1502 145         537 my ( $date2_month_num_03, $date2_day_of_month_03, $date2_year_num_03, $date2_day_of_week_03 ) = date_only_parse($date_two_01);
1503              
1504              
1505 145         409 my $date1_month_num_04 = set_month_to_month_number($date1_month_num_03);
1506 145         447 my $date2_month_num_04 = set_month_to_month_number($date2_month_num_03);
1507              
1508 145         271 my $compare_date_1_and_date_2_00 = '';
1509 145 100 100     1402 if ( $date1_year_num_03 > $date2_year_num_03 )
    100 100        
    100 100        
    100 100        
      100        
1510             {
1511 47         182 $compare_date_1_and_date_2_00 = '1';
1512             }
1513             elsif ( ( $date1_year_num_03 == $date2_year_num_03 ) && ( $date1_month_num_04 > $date2_month_num_04 ) )
1514             {
1515 1         5 $compare_date_1_and_date_2_00 = '1';
1516             }
1517             elsif ( ( $date1_year_num_03 == $date2_year_num_03 ) && ( $date1_month_num_04 == $date2_month_num_04 ) && ( $date1_day_of_month_03 > $date2_day_of_month_03 ) )
1518             {
1519 25         54 $compare_date_1_and_date_2_00 = '1';
1520             }
1521             elsif ( ( $date1_year_num_03 == $date2_year_num_03 ) && ( $date1_month_num_04 == $date2_month_num_04 ) && ( $date1_day_of_month_03 == $date2_day_of_month_03 ) )
1522             {
1523 7         17 $compare_date_1_and_date_2_00 = '0';
1524             }
1525             else
1526             {
1527 65         136 $compare_date_1_and_date_2_00 = '-1';
1528             }
1529              
1530 145         497 return ( $compare_date_1_and_date_2_00 );
1531             }
1532              
1533              
1534              
1535              
1536             ###############################################################################
1537             # Usage : date_offset_in_days( SCALAR, SCALAR )
1538             # Purpose : find a date in the future or past offset by the number of days from the given date
1539             # Returns : - date of the day offset from the given date if successful
1540             # Parameters : (
1541             # : date in any format,
1542             # : number of days offset, positive is future date, negative is past date, zero is current date (no offset)
1543             # : )
1544             # Throws : Throws exception for any invalid input
1545             # Comments : N/A
1546             # See Also : N/A
1547             ###############################################################################
1548             sub date_offset_in_days
1549             {
1550             my (
1551 106     106 1 37405 $date_in_01,
1552             $date_delta_00
1553             )
1554             = @_;
1555              
1556              
1557             # Incoming Inspection
1558 106         180 my $num_input_params_19 = 2;
1559 106 100       347 ( @_ == $num_input_params_19) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_19 parameter(s), a date string followed by the number of offset days. '@_'.\n\n\n";
  6         925  
1560              
1561 100 100       353 ( ref(\$date_in_01) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string '$date_in_01'.\n\n\n";
  1         322  
1562 99 100       287 ( $date_in_01 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$date_in_01'.\n\n\n";
  1         113  
1563 98 100       238 ( date_only_parse($date_in_01) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot parse the date from the input date string '$date_in_01'.\n\n\n";
  2         444  
1564              
1565 96 100       424 ( ref(\$date_delta_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the number of offset days '$date_delta_00'.\n\n\n";
  1         194  
1566 95 100       315 ( $date_delta_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the number of offset days '$date_delta_00'.\n\n\n";
  1         160  
1567 94 100       530 ( $date_delta_00 =~ m/^\-{0,1}\d+$/ ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the number of offset days '$date_delta_00'.\n\n\n";
  1         336  
1568              
1569              
1570 93 100       282 if ( $date_delta_00 == 0 )
1571             {
1572 6         24 return ( format_date( $date_in_01 ) );
1573             }
1574              
1575              
1576 87         282 my ( $date1_month_num_05, $date1_day_of_month_05, $date1_year_num_05, $date1_day_of_week_05 ) = date_only_parse($date_in_01);
1577              
1578             # Total the number of 400 year cycles included in the offset day count
1579 87         418 my $number_of_complete_year_cycles_00 = int( abs($date_delta_00) / $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE );
1580              
1581             # Day offset by multiples of COMPLETE four hundred year cycles
1582 87         469 my $offset_year_00;
1583 87 100       200 if ( $date_delta_00 >= 0 )
1584             {
1585 44         223 $offset_year_00 = $date1_year_num_05 + ( $number_of_complete_year_cycles_00 * $NUMBER_OF_YEAR_PHASES );
1586             }
1587             else
1588             {
1589 43         135 $offset_year_00 = $date1_year_num_05 - ( $number_of_complete_year_cycles_00 * $NUMBER_OF_YEAR_PHASES );
1590             }
1591 87         425 my $offset_month_00 = $date1_month_num_05;
1592 87         139 my $offset_day_of_month_00 = $date1_day_of_month_05;
1593              
1594 87         104 my $days_left_00;
1595 87         368 my $days_left_in_offset_400_year_cycle = get_days_remaining_in_400yr_cycle( $date1_month_num_05, $date1_day_of_month_05, $offset_year_00 );
1596 87         790 my $days_used_in_offset_400_year_cycle = get_number_of_day_within_400yr_cycle( $date1_month_num_05, $date1_day_of_month_05, $offset_year_00 );
1597 87         166 my $day_num_in_400_year_cycle_01;
1598 87 100       278 if ( $date_delta_00 >= 0 )
1599             {
1600 44         209 $days_left_00 = int( $date_delta_00 % $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE );
1601              
1602              
1603 44 100       290 if ( $days_left_in_offset_400_year_cycle >= $days_left_00 )
1604             {
1605 39         111 $day_num_in_400_year_cycle_01 = $days_used_in_offset_400_year_cycle + $days_left_00;
1606             }
1607             else
1608             {
1609 5         13 $day_num_in_400_year_cycle_01 = $days_left_00 - $days_left_in_offset_400_year_cycle;
1610 5         15 $offset_year_00 += $NUMBER_OF_YEAR_PHASES;
1611             }
1612             }
1613             else
1614             {
1615 43         457 $days_left_00 = int( abs($date_delta_00) % $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE );
1616              
1617              
1618 43 100       290 if ( $days_used_in_offset_400_year_cycle > $days_left_00 )
1619             {
1620 38         78 $day_num_in_400_year_cycle_01 = $days_used_in_offset_400_year_cycle - $days_left_00;
1621             }
1622             else
1623             {
1624 5         18 $day_num_in_400_year_cycle_01 = $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE - ($days_left_00 - $days_used_in_offset_400_year_cycle);
1625 5         24 $offset_year_00 -= $NUMBER_OF_YEAR_PHASES;
1626             }
1627             }
1628              
1629 87         317 my $which_400_year_cycle_00 = get_global_year_cycle($offset_year_00);
1630              
1631 87         328 $day_num_in_400_year_cycle_01 = day_number_within_400_year_cycle_to_date( $which_400_year_cycle_00, $day_num_in_400_year_cycle_01 );
1632              
1633 87         265 return ( format_date( $day_num_in_400_year_cycle_01 ) );
1634             }
1635              
1636              
1637              
1638              
1639             ###############################################################################
1640             # Usage : get_global_year_cycle( SCALAR )
1641             # Purpose : get the phase zero year for the given year
1642             # Returns : - the phase zero year containing the given year if input is valid
1643             # Parameters : (
1644             # : year in integer format
1645             # : )
1646             # Throws : Throws exception for any invalid input
1647             # Comments : - Handles all years, even negative years (aka BC)
1648             # : - years repeat in a standard 400 year cycle where year 2000 is defined by this program to be phase '0' and year 2399 is then phase '399'
1649             # : - Examples
1650             # : years 1600 through 1999 return the phase zero year 1600
1651             # : year 2007 returns the phase zero year 2000
1652             # See Also : N/A
1653             ###############################################################################
1654             sub get_global_year_cycle
1655             {
1656             my (
1657 111     111 1 7294 $year_input_08
1658             )
1659             = @_;
1660              
1661              
1662             # Incoming Inspection
1663 111         374 my $num_input_params_20 = 1;
1664 111 100       337 ( @_ == $num_input_params_20) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_20 parameter(s), a date string followed by the number of offset days. '@_'.\n\n\n";
  1         148  
1665              
1666 110 100       419 ( ref(\$year_input_08) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_input_08'.\n\n\n";
  2         327  
1667 108 100       343 ( $year_input_08 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_input_08'.\n\n\n";
  1         148  
1668 107 100       209 ( is_valid_year($year_input_08) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_input_08'.\n\n\n";
  3         793  
1669              
1670              
1671 104         139 my $which_400_year_cycle_01;
1672 104 100       282 if ( $year_input_08 >= 0 )
1673             {
1674 95         311 $which_400_year_cycle_01 = int( $year_input_08 / $NUMBER_OF_YEAR_PHASES ) * $NUMBER_OF_YEAR_PHASES;
1675             }
1676             else
1677             {
1678 9 100       42 if ( ( abs($year_input_08) % $NUMBER_OF_YEAR_PHASES ) == 0 )
1679             {
1680 4         30 $which_400_year_cycle_01 = int( $year_input_08 / $NUMBER_OF_YEAR_PHASES ) * $NUMBER_OF_YEAR_PHASES;
1681             }
1682             else
1683             {
1684 5         50 $which_400_year_cycle_01 = int( $year_input_08 / $NUMBER_OF_YEAR_PHASES ) * $NUMBER_OF_YEAR_PHASES - $NUMBER_OF_YEAR_PHASES;
1685             }
1686             }
1687              
1688 104         1050 return ( $which_400_year_cycle_01 );
1689             }
1690              
1691              
1692              
1693              
1694             ###############################################################################
1695             # Usage : get_number_of_days_in_month( SCALAR, SCALAR )
1696             # Purpose : get the number of days in a specific month
1697             # Returns : - number of days in the month if successful
1698             # Parameters : (
1699             # : alpha or month integer<1-12>,
1700             # : year integer,
1701             # : )
1702             # Throws : Throws exception for any invalid input
1703             # Comments : Handles all years, even negative years (aka BC)
1704             # See Also : N/A
1705             ###############################################################################
1706             sub get_number_of_days_in_month
1707             {
1708             my (
1709 13209     13209 1 37129 $month_input_04,
1710             $year_input_02,
1711             )
1712             = @_;
1713              
1714              
1715             # Incoming Inspection
1716 13209         15640 my $num_input_params_21 = 2;
1717 13209 100       27652 ( @_ == $num_input_params_21) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_21 parameter(s), (month, year). '@_'.\n\n\n";
  7         1051  
1718              
1719 13202 100       31338 ( ref(\$month_input_04) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$month_input_04'.\n\n\n";
  1         128  
1720 13201 100       28261 ( $month_input_04 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$month_input_04'.\n\n\n";
  1         135  
1721 13200 100       36299 ( is_valid_month($month_input_04) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$month_input_04'.\n\n\n";
  10         1505  
1722              
1723 13190 100       31473 ( ref(\$year_input_02) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_input_02'.\n\n\n";
  2         438  
1724 13188 100       26759 ( $year_input_02 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_input_02'.\n\n\n";
  1         136  
1725 13187 100       25807 ( is_valid_year($year_input_02) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_input_02'.\n\n\n";
  1         129  
1726              
1727              
1728 13186         26251 my $month_num_06 = set_month_to_month_number($month_input_04);
1729              
1730             # Months with 30 days ( April June September November )
1731 13186 100 100     114048 if ( ( $month_num_06 == 4 ) || ( $month_num_06 == 6 ) || ( $month_num_06 == 9 ) || ( $month_num_06 == 11 ) )
    100 100        
    100 100        
      100        
1732             {
1733 3813         13997 return ( 30 );
1734             }
1735             # February (NON leap year)
1736             elsif ( ( $month_num_06 == 2 ) && (!( is_leap_year($year_input_02) ) ) )
1737             {
1738 1230         4900 return ( 28 );
1739             }
1740             # February (leap year)
1741             # elsif ( ( $month_num_06 == 2 ) && ( is_leap_year($year_input_02) ) )
1742             elsif ( $month_num_06 == 2 )
1743             {
1744 690         2906 return ( 29 );
1745             }
1746             # Months with 31 days
1747             else
1748             {
1749 7453         27077 return ( 31 );
1750             }
1751              
1752             }
1753              
1754              
1755              
1756              
1757             ###############################################################################
1758             # Usage : get_days_remaining_in_month( SCALAR, SCALAR, SCALAR )
1759             # Purpose : find out how many days are remaining in the month from the given date
1760             # Returns : number of days left if successful
1761             # Parameters : (
1762             # : alpha or month integer<1-12>,
1763             # : day of month integer<1-N>,
1764             # : year integer,
1765             # : )
1766             # Throws : Throws exception for any invalid input
1767             # Comments : - Handles all years, even negative years (aka BC)
1768             # : - if the last day of the month is given, 0 is returned
1769             # See Also : N/A
1770             ###############################################################################
1771             sub get_days_remaining_in_month
1772             {
1773             my (
1774 50     50 1 14552 $month_input_05,
1775             $day_of_month_input_01,
1776             $year_input_03,
1777             )
1778             = @_;
1779              
1780              
1781             # Incoming Inspection
1782 50         83 my $num_input_params_22 = 3;
1783 50 100       141 ( @_ == $num_input_params_22) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_22 parameter(s), (month, day_of_month, year). '@_'.\n\n\n";
  1         276  
1784              
1785              
1786 49 100       141 ( ref(\$month_input_05) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$month_input_05'.\n\n\n";
  1         132  
1787 48 100       110 ( $month_input_05 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$month_input_05'.\n\n\n";
  1         158  
1788 47 100       95 ( is_valid_month($month_input_05) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$month_input_05'.\n\n\n";
  1         162  
1789              
1790 46 100       143 ( ref(\$year_input_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_input_03'.\n\n\n";
  1         157  
1791 45 100       114 ( $year_input_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_input_03'.\n\n\n";
  1         156  
1792 44 100       87 ( is_valid_year($year_input_03) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_input_03'.\n\n\n";
  1         169  
1793              
1794 43 100       105 ( ref(\$day_of_month_input_01) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day of month '$day_of_month_input_01'.\n\n\n";
  1         176  
1795 42 100       99 ( $day_of_month_input_01 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day of month '$day_of_month_input_01'.\n\n\n";
  1         147  
1796 41 100       83 ( is_valid_day_of_month($month_input_05, $day_of_month_input_01, $year_input_03) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value for the day of month (1-31) '$day_of_month_input_01'.\n\n\n";
  16         2493  
1797              
1798              
1799 25         55 my $month_num_07 = set_month_to_month_number($month_input_05);
1800              
1801             # Months with 30 days ( April June September November )
1802 25 100 100     256 if ( ( $month_num_07 == 4 ) || ( $month_num_07 == 6 ) || ( $month_num_07 == 9 ) || ( $month_num_07 == 11 ) )
    100 100        
    100 100        
      100        
1803             {
1804 6         31 return ( 30 - $day_of_month_input_01 );
1805             }
1806             # February (NON leap year)
1807             elsif ( ( $month_num_07 == 2 ) && (!( is_leap_year($year_input_03) ) ) )
1808             {
1809 5         29 return ( 28 - $day_of_month_input_01 );
1810             }
1811             # February (leap year)
1812             # elsif ( ( $month_num_07 == 2 ) && ( is_leap_year($year_input_03) ) )
1813             elsif ( $month_num_07 == 2 )
1814             {
1815 3         19 return ( 29 - $day_of_month_input_01 );
1816             }
1817             # Months with 31 days
1818             else
1819             {
1820 11         65 return ( 31 - $day_of_month_input_01 );
1821             }
1822              
1823             }
1824              
1825              
1826              
1827              
1828             ###############################################################################
1829             # Usage : get_days_remaining_in_year( SCALAR, SCALAR, SCALAR )
1830             # Purpose : find out how many days are remaining in the year from the given date
1831             # Returns : number of days left if successful
1832             # Parameters : (
1833             # : alpha or month integer<1-12>,
1834             # : day of month integer<1-N>,
1835             # : year integer,
1836             # : )
1837             # Throws : Throws exception for any invalid input
1838             # Comments : - Handles all years, even negative years (aka BC)
1839             # : - if the last day of the year is given, 0 is returned
1840             # See Also : N/A
1841             ###############################################################################
1842             sub get_days_remaining_in_year
1843             {
1844             my (
1845 26     26 1 11464 $month_input_06,
1846             $day_of_month_input_02,
1847             $year_input_04,
1848             )
1849             = @_;
1850              
1851              
1852             # Incoming Inspection
1853 26         46 my $num_input_params_23 = 3;
1854 26 100       82 ( @_ == $num_input_params_23) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_23 parameter(s), (month, day_of_month, year). '@_'.\n\n\n";
  2         299  
1855              
1856              
1857 24 100       87 ( ref(\$month_input_06) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$month_input_06'.\n\n\n";
  1         423  
1858 23 100       70 ( $month_input_06 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$month_input_06'.\n\n\n";
  1         141  
1859 22 100       52 ( is_valid_month($month_input_06) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$month_input_06'.\n\n\n";
  4         554  
1860              
1861 18 100       60 ( ref(\$year_input_04) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_input_04'.\n\n\n";
  1         155  
1862 17 100       57 ( $year_input_04 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_input_04'.\n\n\n";
  1         141  
1863 16 100       36 ( is_valid_year($year_input_04) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_input_04'.\n\n\n";
  1         168  
1864              
1865 15 100       47 ( ref(\$day_of_month_input_02) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day of month '$day_of_month_input_02'.\n\n\n";
  1         162  
1866 14 100       42 ( $day_of_month_input_02 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day of month '$day_of_month_input_02'.\n\n\n";
  1         171  
1867 13 100       31 ( is_valid_day_of_month($month_input_06, $day_of_month_input_02, $year_input_04) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value for the day of month (1-31) '$day_of_month_input_02'.\n\n\n";
  4         702  
1868              
1869              
1870 9         21 my $month_num_08 = set_month_to_month_number($month_input_06);
1871              
1872 9         36 return ( get_num_days_in_year( $year_input_04 ) - number_of_day_within_year( "${month_num_08}/${day_of_month_input_02}/${year_input_04}" ) );
1873             }
1874              
1875              
1876              
1877              
1878             ###############################################################################
1879             # Usage : get_number_of_day_within_400yr_cycle( SCALAR, SCALAR, SCALAR )
1880             # Purpose : find the number of the day within the standard 400 year cycle
1881             # Returns : day number if successful
1882             # Parameters : (
1883             # : alpha or month integer<1-12>,
1884             # : day of month integer<1-N>,
1885             # : year integer,
1886             # : )
1887             # Throws : Throws exception for any invalid input
1888             # Comments : - Handles all years, even negative years (aka BC)
1889             # : - years repeat in a standard 400 year cycle where year 2000 is defined by this program to be phase '0' and year 2399 is then phase '399'
1890             # : - this would be a very LARGE integer for the 1990's
1891             # : - Jan 1, 2000 would return '1'
1892             # See Also : N/A
1893             ###############################################################################
1894             sub get_number_of_day_within_400yr_cycle
1895             {
1896             my (
1897 208     208 1 10606 $month_input_07,
1898             $day_of_month_input_03,
1899             $year_input_05,
1900             )
1901             = @_;
1902              
1903              
1904             # Incoming Inspection
1905 208         399 my $num_input_params_24 = 3;
1906 208 100       577 ( @_ == $num_input_params_24) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_24 parameter(s), (month, day_of_month, year). '@_'.\n\n\n";
  1         147  
1907              
1908              
1909 207 100       726 ( ref(\$month_input_07) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$month_input_07'.\n\n\n";
  1         171  
1910 206 100       2503 ( $month_input_07 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$month_input_07'.\n\n\n";
  1         159  
1911 205 100       447 ( is_valid_month($month_input_07) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$month_input_07'.\n\n\n";
  5         794  
1912              
1913 200 100       696 ( ref(\$year_input_05) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_input_05'.\n\n\n";
  1         140  
1914 199 100       547 ( $year_input_05 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_input_05'.\n\n\n";
  1         140  
1915 198 100       453 ( is_valid_year($year_input_05) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_input_05'.\n\n\n";
  1         164  
1916              
1917 197 100       822 ( ref(\$day_of_month_input_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day of month '$day_of_month_input_03'.\n\n\n";
  1         133  
1918 196 100       493 ( $day_of_month_input_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day of month '$day_of_month_input_03'.\n\n\n";
  1         134  
1919 195 100       402 ( is_valid_day_of_month($month_input_07, $day_of_month_input_03, $year_input_05) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value for the day of month (1-31) '$day_of_month_input_03'.\n\n\n";
  3         440  
1920              
1921              
1922 192         404 my $month_num_09 = set_month_to_month_number($month_input_07);
1923              
1924 192         624 my $year_phase_01 = get_year_phase($year_input_05);
1925 192         410 my $day_num_in_400_year_cycle_00 = 0;
1926 192         260 my $iii_000 = 0;
1927 192         588 for ( $iii_000=0; $iii_000<$year_phase_01; $iii_000++ )
1928             {
1929 62063         105563 $day_num_in_400_year_cycle_00 += get_num_days_in_year($iii_000);
1930             }
1931 192         1319 $day_num_in_400_year_cycle_00 += number_of_day_within_year( "${month_num_09}/${day_of_month_input_03}/${iii_000}" );
1932              
1933 192         814 return ( $day_num_in_400_year_cycle_00 );
1934              
1935             }
1936              
1937              
1938              
1939              
1940             ###############################################################################
1941             # Usage : get_days_remaining_in_400yr_cycle( SCALAR, SCALAR, SCALAR )
1942             # Purpose : find the number of days remaining from the given date to the end of the current standard 400 year cycle
1943             # Returns : number of days left if successful
1944             # Parameters : (
1945             # : alpha or month integer<1-12>,
1946             # : day of month integer<1-N>,
1947             # : year integer,
1948             # : )
1949             # Throws : Throws exception for any invalid input
1950             # Comments : - Handles all years, even negative years (aka BC)
1951             # : - years repeat in a standard 400 year cycle where year 2000 is defined by this program to be phase '0' and year 2399 is then phase '399'
1952             # : - this would be a very SMALL integer for the 1990's
1953             # : - Jan 1, 2000 would return '146096'. There are a total of 146,097 days in the standard 400 year cycle.
1954             # See Also : N/A
1955             ###############################################################################
1956             sub get_days_remaining_in_400yr_cycle
1957             {
1958             my (
1959 109     109 1 17570 $month_input_08,
1960             $day_of_month_input_04,
1961             $year_input_06,
1962             )
1963             = @_;
1964              
1965              
1966             # Incoming Inspection
1967 109         233 my $num_input_params_25 = 3;
1968 109 100       319 ( @_ == $num_input_params_25) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_25 parameter(s), (month, day_of_month, year). '@_'.\n\n\n";
  1         8616  
1969              
1970              
1971 108 100       379 ( ref(\$month_input_08) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$month_input_08'.\n\n\n";
  1         154  
1972 107 100       518 ( $month_input_08 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$month_input_08'.\n\n\n";
  1         153  
1973 106 100       234 ( is_valid_month($month_input_08) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$month_input_08'.\n\n\n";
  4         825  
1974              
1975 102 100       330 ( ref(\$year_input_06) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_input_06'.\n\n\n";
  1         161  
1976 101 100       304 ( $year_input_06 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_input_06'.\n\n\n";
  1         140  
1977 100 100       180 ( is_valid_year($year_input_06) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_input_06'.\n\n\n";
  1         3808  
1978              
1979 99 100       316 ( ref(\$day_of_month_input_04) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day of month '$day_of_month_input_04'.\n\n\n";
  1         152  
1980 98 100       293 ( $day_of_month_input_04 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day of month '$day_of_month_input_04'.\n\n\n";
  1         167  
1981 97 100       276 ( is_valid_day_of_month($month_input_08, $day_of_month_input_04, $year_input_06) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value for the day of month (1-31) '$day_of_month_input_04'.\n\n\n";
  2         287  
1982              
1983              
1984 95         200 my $month_num_10 = set_month_to_month_number($month_input_08);
1985              
1986 95         425 return ( $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE - get_number_of_day_within_400yr_cycle( $month_num_10, $day_of_month_input_04, $year_input_06 ) );
1987             }
1988              
1989              
1990              
1991              
1992             ###############################################################################
1993             # Usage : day_number_within_year_to_date( SCALAR, SCALAR )
1994             # Purpose : converts the number of the day within the year to a date
1995             # Returns : date if successful
1996             # Parameters : (
1997             # : year integer,
1998             # : number of day in year <1-365/6>,
1999             # : )
2000             # Throws : Throws exception for any invalid input
2001             # Comments : Handles all years, even negative years (aka BC)
2002             # See Also : N/A
2003             ###############################################################################
2004             sub day_number_within_year_to_date
2005             {
2006             my (
2007 170     170 1 11530 $year_input_07,
2008             $day_number_in_year_00,
2009             )
2010             = @_;
2011              
2012              
2013             # Incoming Inspection
2014 170         272 my $num_input_params_26 = 2;
2015 170 100       491 ( @_ == $num_input_params_26) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_26 parameter(s), (month, day_of_month, year). '@_'.\n\n\n";
  4         523  
2016              
2017 166 100       700 ( ref(\$year_input_07) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_input_07'.\n\n\n";
  1         120  
2018 165 100       488 ( $year_input_07 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_input_07'.\n\n\n";
  1         123  
2019 164 100       588 ( is_valid_year($year_input_07) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_input_07'.\n\n\n";
  1         129  
2020              
2021 163 100       555 ( ref(\$day_number_in_year_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day number within the year '$day_number_in_year_00'.\n\n\n";
  1         123  
2022 162 100       508 ( $day_number_in_year_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day number within the year '$day_number_in_year_00'.\n\n\n";
  1         127  
2023              
2024              
2025 161 100       373 if ( !(is_leap_year($year_input_07)) )
2026             {
2027 113 100 100     1886 ( ( $day_number_in_year_00 =~ m/^(\d{1,3})$/ ) && ( $1 > 0 ) && ( $1 < 366 ) ) or croak "\n\n ($0) '${\(caller(0))[3]}' The number of the day within a NON leap must be in the range of 1-365 '$day_number_in_year_00'.\n\n\n";
  5   100     671  
2028             }
2029             else
2030             {
2031 48 100 100     596 ( ( $day_number_in_year_00 =~ m/^(\d{1,3})$/ ) && ( $1 > 0 ) && ( $1 < 367 ) ) or croak "\n\n ($0) '${\(caller(0))[3]}' The number of the day within a LEAP must be in the range of 1-366 '$day_number_in_year_00'.\n\n\n";
  3   100     513  
2032             }
2033              
2034              
2035 153         244 my $date_from_num_00;
2036              
2037 153 100       532 if ( $day_number_in_year_00 < 32 )
    100          
2038             {
2039 17         53 $date_from_num_00 = "1/" . $day_number_in_year_00 . "/$year_input_07";
2040             }
2041             elsif ( !( is_leap_year($year_input_07) ) )
2042             {
2043 102         284 foreach ($day_number_in_year_00)
2044             {
2045             SWITCH:
2046             {
2047 102 100       174 if ( $_ < 60 ) { $date_from_num_00 = "2/" . ($_ - 31) . "/$year_input_07"; last SWITCH; } # if ( $_ < (31 + 29) )
  102         334  
  2         7  
  2         6  
2048 100 100       360 if ( $_ < 91 ) { $date_from_num_00 = "3/" . ($_ - 59) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 32) ) $date_from_num_00 = "3/" . ($_ - (31 + 28)) . "/$year_input_07";
  2         7  
  2         6  
2049 98 100       247 if ( $_ < 121 ) { $date_from_num_00 = "4/" . ($_ - 90) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 31) ) $date_from_num_00 = "4/" . ($_ - (31 + 28 + 31)) . "/$year_input_07";
  2         7  
  2         6  
2050 96 100       262 if ( $_ < 152 ) { $date_from_num_00 = "5/" . ($_ - 120) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 30 + 32) ) $date_from_num_00 = "5/" . ($_ - (31 + 28 + 31 + 30)) . "/$year_input_07";
  2         8  
  2         6  
2051 94 100       281 if ( $_ < 182 ) { $date_from_num_00 = "6/" . ($_ - 151) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 30 + 31 + 31) ) $date_from_num_00 = "6/" . ($_ - (31 + 28 + 31 + 30 + 31)) . "/$year_input_07";
  3         16  
  3         11  
2052 91 100       245 if ( $_ < 213 ) { $date_from_num_00 = "7/" . ($_ - 181) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 30 + 31 + 30 + 32) ) $date_from_num_00 = "7/" . ($_ - (31 + 28 + 31 + 30 + 31 + 30)) . "/$year_input_07";
  71         320  
  71         303  
2053 20 100       52 if ( $_ < 244 ) { $date_from_num_00 = "8/" . ($_ - 212) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 32) ) $date_from_num_00 = "8/" . ($_ - (31 + 28 + 31 + 30 + 31 + 30 + 31)) . "/$year_input_07";
  2         8  
  2         7  
2054 18 100       52 if ( $_ < 274 ) { $date_from_num_00 = "9/" . ($_ - 243) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 31) ) $date_from_num_00 = "9/" . ($_ - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31)) . "/$year_input_07";
  2         5  
  2         7  
2055 16 100       38 if ( $_ < 305 ) { $date_from_num_00 = "10/" . ($_ - 273) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 32) ) $date_from_num_00 = "10/" . ($_ - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30)) . "/$year_input_07";
  3         16  
  3         10  
2056 13 100       63 if ( $_ < 335 ) { $date_from_num_00 = "11/" . ($_ - 304) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 31) ) $date_from_num_00 = "11/" . ($_ - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31)) . "/$year_input_07";
  2         8  
  2         6  
2057 11         96 $date_from_num_00 = "12/" . ($_ - 334) . "/$year_input_07"; # $date_from_num_00 = "12/" . ($_ - (31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30)) . "/$year_input_07";
2058             }
2059             }
2060             }
2061             else
2062             {
2063 34         65 foreach ($day_number_in_year_00)
2064             {
2065             SWITCH:
2066             {
2067 34 100       42 if ( $_ < 61 ) { $date_from_num_00 = "2/" . ($_ - 31) . "/$year_input_07"; last SWITCH; } # if ( $_ < (31 + 30) )
  34         93  
  3         14  
  3         12  
2068 31 100       72 if ( $_ < 92 ) { $date_from_num_00 = "3/" . ($_ - 60) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 32) ) $date_from_num_00 = "3/" . ($_ - (31 + 29)) . "/$year_input_07";
  3         11  
  3         9  
2069 28 100       63 if ( $_ < 122 ) { $date_from_num_00 = "4/" . ($_ - 91) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 31) ) $date_from_num_00 = "4/" . ($_ - (31 + 29 + 31)) . "/$year_input_07";
  3         11  
  3         8  
2070 25 100       55 if ( $_ < 153 ) { $date_from_num_00 = "5/" . ($_ - 121) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 30 + 32) ) $date_from_num_00 = "5/" . ($_ - (31 + 29 + 31 + 30)) . "/$year_input_07";
  3         10  
  3         10  
2071 22 100       50 if ( $_ < 183 ) { $date_from_num_00 = "6/" . ($_ - 152) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 30 + 31 + 31) ) $date_from_num_00 = "6/" . ($_ - (31 + 29 + 31 + 30 + 31)) . "/$year_input_07";
  3         10  
  3         10  
2072 19 100       44 if ( $_ < 214 ) { $date_from_num_00 = "7/" . ($_ - 182) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 30 + 31 + 30 + 32) ) $date_from_num_00 = "7/" . ($_ - (31 + 29 + 31 + 30 + 31 + 30)) . "/$year_input_07";
  3         8  
  3         11  
2073 16 100       33 if ( $_ < 245 ) { $date_from_num_00 = "8/" . ($_ - 213) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 30 + 31 + 30 + 31 + 32) ) $date_from_num_00 = "8/" . ($_ - (31 + 29 + 31 + 30 + 31 + 30 + 31)) . "/$year_input_07";
  3         11  
  3         10  
2074 13 100       43 if ( $_ < 275 ) { $date_from_num_00 = "9/" . ($_ - 244) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 31) ) $date_from_num_00 = "9/" . ($_ - (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31)) . "/$year_input_07";
  3         9  
  3         9  
2075 10 100       26 if ( $_ < 306 ) { $date_from_num_00 = "10/" . ($_ - 274) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 32) ) $date_from_num_00 = "10/" . ($_ - (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30)) . "/$year_input_07";
  3         10  
  3         10  
2076 7 100       19 if ( $_ < 336 ) { $date_from_num_00 = "11/" . ($_ - 305) . "/$year_input_07"; last SWITCH; } # elsif ( $_ < (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 31) ) $date_from_num_00 = "11/" . ($_ - (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31)) . "/$year_input_07";
  3         10  
  3         7  
2077 4         21 $date_from_num_00 = "12/" . ($_ - 335) . "/$year_input_07"; # $date_from_num_00 = "12/" . ($_ - (31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30)) . "/$year_input_07";
2078             }
2079             }
2080             }
2081              
2082 153         612 return ( format_date( $date_from_num_00 ) );
2083             }
2084              
2085              
2086              
2087              
2088             ###############################################################################
2089             # Usage : day_number_within_400_year_cycle_to_date( SCALAR, SCALAR )
2090             # Purpose : converts the number of the day within the standard 400 year cycle to a date
2091             # Returns : date if successful
2092             # Parameters : (
2093             # : 400 year cycle, (i.e. ... -400, 0, 400, ... 1600, 2000, 2400, ...)
2094             # : number of day in the standard 400 year cycle <1-146097>,
2095             # : )
2096             # Throws : Throws exception for any invalid input
2097             # Comments : - Handles all years, even negative years (aka BC)
2098             # : - years repeat in a standard 400 year cycle where year 2000 is defined by this program to be phase '0' and year 2399 is then phase '399'
2099             # See Also : N/A
2100             ###############################################################################
2101             sub day_number_within_400_year_cycle_to_date
2102             {
2103             my (
2104 109     109 1 8084 $four_hundred_year_cycle_00,
2105             $day_number_in_400_year_cycle_00,
2106             )
2107             = @_;
2108              
2109              
2110             # Incoming Inspection
2111 109         191 my $num_input_params_27 = 2;
2112 109 100       303 ( @_ == $num_input_params_27) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_27 parameter(s), (400 year cycle<-400,0,400,...,2000>, day number within 400 year cycle<1 - 146097> ). '@_'.\n\n\n";
  5         527  
2113              
2114 104 100       383 ( ref(\$four_hundred_year_cycle_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the 400 year cycle<-400,0,400,...,2000>, day number within 400 year cycle<1 - 146097> '$four_hundred_year_cycle_00'.\n\n\n";
  1         92  
2115 103 100       299 ( $four_hundred_year_cycle_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the 400 year cycle<-400,0,400,...,2000>, day number within 400 year cycle<1 - 146097> '$four_hundred_year_cycle_00'.\n\n\n";
  1         122  
2116 102 100       341 ( is_valid_400_year_cycle($four_hundred_year_cycle_00) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the 400 year cycle<-400,0,400,...,2000>, day number within 400 year cycle<1 - 146097> '$four_hundred_year_cycle_00'.\n\n\n";
  4         450  
2117              
2118 98 100       332 ( ref(\$day_number_in_400_year_cycle_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day number within the 400 year cycle '$day_number_in_400_year_cycle_00'.\n\n\n";
  1         98  
2119 97 100       294 ( $day_number_in_400_year_cycle_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day number within the 400 year cycle '$day_number_in_400_year_cycle_00'.\n\n\n";
  1         125  
2120 96 100 100     1043 ( ( $day_number_in_400_year_cycle_00 =~ m/^(\d{1,6})$/ ) && ( $1 > 0 ) && ( $1 <= $NUMBER_OF_DAYS_IN_400_YEAR_CYCLE ) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer (1 - 146097) for the day number within the 400 year cycle '$day_number_in_400_year_cycle_00'.\n\n\n";
  3   100     401  
2121              
2122              
2123 93         704 my $current_day_count_00 = $day_number_in_400_year_cycle_00;
2124 93         119 my $iii_002;
2125 93         268 for ( $iii_002=0; $iii_002<$NUMBER_OF_YEAR_PHASES; $iii_002++ )
2126             {
2127 30735         163241 my $days_in_this_year_00 = get_num_days_in_year($iii_002);
2128 30735 100       58425 if ( $current_day_count_00 > $days_in_this_year_00 )
2129             {
2130 30642         110177 $current_day_count_00 -= $days_in_this_year_00;
2131             }
2132             else
2133             {
2134 93         254 last;
2135             }
2136             }
2137              
2138 93         473 my ( $month_num_11, $day_of_month_11, $year_num_11, $day_of_week_11 ) = date_only_parse(day_number_within_year_to_date($iii_002, $current_day_count_00));
2139 93         236 $year_num_11 += $four_hundred_year_cycle_00;
2140              
2141 93         379 my $date_from_num_01 = "${month_num_11}/${day_of_month_11}/${year_num_11}";
2142              
2143 93         230 return ( format_date( $date_from_num_01 ) );
2144             }
2145              
2146              
2147              
2148              
2149             ###############################################################################
2150             # Usage : Function is overloaded to accept EITHER a date string OR a date
2151             # : component.
2152             # : 1) Date string,
2153             # : format_date( SCALAR, )
2154             # : 2) Month, dayofmonth, year,
2155             # : format_date( SCALAR, SCALAR, SCALAR, )
2156             # Purpose : Formats dates
2157             # Returns : date string if successful
2158             # Parameters : 1) ( date string in any format, )
2159             # : OR
2160             # : 2) ( month, day of month, year, )
2161             # Throws : Throws exception for any invalid input
2162             # Comments : - Handles all years, even negative years (aka BC)
2163             # : - It does NOT output time, time zone or any other time parameter
2164             # : other than a CONSTANT 12noon time when a time component is
2165             # : included in the format.
2166             # : - Format options
2167             # : -> 'mm/dd/yyyy'
2168             # : 'A' -> 'Mon Sep 17 12:00:00 2007' (time component is ALWAYS 12 noon)
2169             # : 'B' -> 'September 17, 2007'
2170             # : 'C' -> '17 September, 2007'
2171             # : 'D' -> 'YYYY-MM-DD'
2172             # See Also : N/A
2173             ###############################################################################
2174             sub format_date
2175             {
2176              
2177              
2178             # Incoming Inspection
2179 441 100 100 441 1 22855 ( ( @_ > 0 ) && ( @_ < 5 ) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Should have a date string and an optional format field, or a list of month,dayofmonth,year and an optional format field. '@_'.\n\n\n";
  2         256  
2180              
2181              
2182 439         918 my $format_selection_00 = '';
2183 439         543 my ($mmonth_00, $dday_00, $yyear_00, $day_of_week_04);
2184             # Parsing date string with optional format selection
2185 439 100 100     2002 if (( @_ == 1 ) || ( @_ == 2 ) )
2186             {
2187 382 100       1312 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string. '$_[0]'.\n\n\n";
  1         134  
2188 381 100       1025 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$_[0]'.\n\n\n";
  1         101  
2189 380 100       1033 ( date_only_parse($_[0]) ) or croak "\n\n ($0) '${\(caller(0))[3]}' date string, '$_[0]', cannot be parsed.\n\n\n";
  14         2077  
2190 366         600 my $date_in_02;
2191 366 100       840 if ( @_ == 1 )
2192             {
2193 360         649 $date_in_02 = $_[0];
2194             }
2195             else
2196             {
2197 6 100       25 ( ref(\$_[1]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the desired date format. '$_[1]'.\n\n\n";
  1         185  
2198 5 100       20 ( $_[1] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the desired date format '$_[1]'.\n\n\n";
  1         152  
2199 4         13 ( $date_in_02, $format_selection_00 ) = @_;
2200             }
2201 364         1075 ($mmonth_00, $dday_00, $yyear_00, $day_of_week_04) = date_only_parse($date_in_02);
2202             }
2203             # Individual date components with optional format selection
2204             else
2205             {
2206 57 100       196 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$_[0]'.\n\n\n";
  2         225  
2207 55 100       167 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$_[0]'.\n\n\n";
  2         296  
2208 53 100       123 ( is_valid_month($_[0]) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$_[0]'.\n\n\n";
  6         831  
2209              
2210 47 100       171 ( ref(\$_[2]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$_[2]'.\n\n\n";
  2         239  
2211 45 100       137 ( $_[2] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$_[2]'.\n\n\n";
  2         261  
2212 43 100       121 ( is_valid_year($_[2]) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$_[2]'.\n\n\n";
  1         137  
2213              
2214 42 100       127 ( ref(\$_[1]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day of month '$_[1]'.\n\n\n";
  2         212  
2215 40 100       491 ( $_[1] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day of month '$_[1]'.\n\n\n";
  2         290  
2216 38 100       115 ( is_valid_day_of_month($_[0], $_[1], $_[2]) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value for the day of month (1-31) '$_[1]'.\n\n\n";
  2         280  
2217              
2218 36         150 ($mmonth_00, $dday_00, $yyear_00 ) = ( $_[0], $_[1], $_[2] );
2219 36         203 $day_of_week_04 = get_numeric_day_of_week( $mmonth_00, $dday_00, $yyear_00 );
2220 36 100       121 if ( @_ == 4 )
2221             {
2222 12 100       41 ( ref(\$_[3]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the desired date format. '$_[3]'.\n\n\n";
  1         151  
2223 11 100       28 ( $_[3] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the desired date format '$_[3]'.\n\n\n";
  1         229  
2224 10         23 $format_selection_00 = $_[3];
2225             }
2226             }
2227              
2228 398         1219 $mmonth_00 = set_month_to_month_number($mmonth_00);
2229              
2230 398         647 my $formatted_date_00;
2231             # '12/30/1999'
2232 398 100       1194 if ( uc($format_selection_00) eq '' ) # default format
    100          
    100          
    100          
    100          
2233             {
2234 384         5181 $formatted_date_00 = sprintf "%02d/%02d/%d", $mmonth_00, $dday_00, $yyear_00;
2235             }
2236             # 'Sun Feb 29 12:00:00 1604'
2237             elsif ( uc($format_selection_00) eq 'A' )
2238             {
2239 6         23 my $day_of_week_abbreviated_00 = set_day_to_day_name_abbrev( $day_of_week_04 );
2240 6         17 my $month_abbreviated_00 = set_month_to_month_name_abbrev( $mmonth_00 );
2241 6         47 $formatted_date_00 = sprintf "%3s %3s %2d 12:00:00 %d", $day_of_week_abbreviated_00, $month_abbreviated_00, $dday_00, $yyear_00;
2242             }
2243             # 'September 17, 2007'
2244             elsif ( uc($format_selection_00) eq 'B' )
2245             {
2246 1         6 my $month_12 = set_month_to_month_name_full( $mmonth_00 );
2247 1         12 $formatted_date_00 = sprintf "%3s %01d, %d", $month_12, $dday_00, $yyear_00;
2248             }
2249             # '17 September, 2007'
2250             elsif ( uc($format_selection_00) eq 'C' )
2251             {
2252 1         4 my $month_14 = set_month_to_month_name_full( $mmonth_00 );
2253 1         9 $formatted_date_00 = sprintf "%01d %3s, %d", $dday_00, $month_14, $yyear_00;
2254             }
2255             # 'YYYY-MM-DD' (ex: 2007-09-01 )
2256             elsif ( uc($format_selection_00) eq 'D' )
2257             {
2258 5         15 my $month_15 = set_month_to_month_number( $mmonth_00 );
2259 5         31 $formatted_date_00 = sprintf "%d-%02d-%02d", $yyear_00, $month_15, $dday_00;
2260             }
2261             else
2262             {
2263 1         4 croak "\n\n ($0) '${\(caller(0))[3]}' This date format selection, '$format_selection_00', is not recognized. Refer to documentation for allowable options.\n\n\n";
  1         135  
2264             }
2265              
2266 397         2649 return ($formatted_date_00);
2267             }
2268              
2269              
2270              
2271              
2272             ###############################################################################
2273             # Usage : get_first_of_month_day_of_week( SCALAR, SCALAR )
2274             # Purpose : get the day of the week for the first of the month for a specified month/year combination
2275             # Returns : - day of the week (1-7) if successful
2276             # Parameters : (
2277             # : alpha or month integer<1-12>,
2278             # : year integer,
2279             # : )
2280             # Throws : Throws exception for any invalid input
2281             # Comments : - Handles all years, even negative years (aka BC)
2282             # : - <1 for Mon ... 7 for Sun>
2283             # See Also : N/A
2284             ###############################################################################
2285             sub get_first_of_month_day_of_week
2286             {
2287             my (
2288 220833     220833 1 367604 $month_input_09,
2289             $year_in_05,
2290             )
2291             = @_;
2292              
2293              
2294             # Incoming Inspection
2295 220833         260943 my $num_input_params_28 = 2;
2296 220833 100       539732 ( @_ == $num_input_params_28) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_28 parameter(s), (month, year). '@_'.\n\n\n";
  2         382  
2297              
2298 220831 100       552323 ( ref(\$month_input_09) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$month_input_09'.\n\n\n";
  1         127  
2299 220830 100       534229 ( $month_input_09 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$month_input_09'.\n\n\n";
  1         133  
2300 220829 100       421789 ( is_valid_month($month_input_09) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$month_input_09'.\n\n\n";
  4         514  
2301              
2302 220825 100       583741 ( ref(\$year_in_05) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$year_in_05'.\n\n\n";
  1         147  
2303 220824 100       531974 ( $year_in_05 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$year_in_05'.\n\n\n";
  1         147  
2304 220823 100       404363 ( is_valid_year($year_in_05) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$year_in_05'.\n\n\n";
  1         152  
2305              
2306              
2307 220822         476111 my $month_num_12 = set_month_to_month_number($month_input_09);
2308 220822         504318 my $year_phase_02 = get_year_phase( $year_in_05 );
2309 220822         810457 my $first_of_month_day_of_week_00 = set_day_to_day_number($DAY_OF_WEEK_ON_FIRST_OF_YEAR{$year_phase_02});
2310 220822 100       667149 if ( !(is_leap_year($year_in_05) ) )
2311             {
2312 167262         282977 foreach ($month_num_12)
2313             {
2314             SWITCH:
2315             {
2316 167262 100       174123 if ( $_ == 2 ) { $first_of_month_day_of_week_00 += 31; last SWITCH; }
  167262         361997  
  13943         17647  
  13943         38275  
2317 153319 100       298539 if ( $_ == 3 ) { $first_of_month_day_of_week_00 += 59; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28;
  13938         19121  
  13938         37265  
2318 139381 100       272542 if ( $_ == 4 ) { $first_of_month_day_of_week_00 += 90; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31;
  13938         17069  
  13938         36228  
2319 125443 100       225066 if ( $_ == 5 ) { $first_of_month_day_of_week_00 += 120; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30;
  13938         16378  
  13938         36990  
2320 111505 100       228678 if ( $_ == 6 ) { $first_of_month_day_of_week_00 += 151; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30 + 31;
  13938         18923  
  13938         42488  
2321 97567 100       176955 if ( $_ == 7 ) { $first_of_month_day_of_week_00 += 181; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30 + 31 + 30;
  13938         19141  
  13938         42294  
2322 83629 100       143839 if ( $_ == 8 ) { $first_of_month_day_of_week_00 += 212; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30 + 31 + 30 + 31;
  13938         29139  
  13938         58362  
2323 69691 100       123591 if ( $_ == 9 ) { $first_of_month_day_of_week_00 += 243; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31;
  13938         18744  
  13938         41035  
2324 55753 100       113301 if ( $_ == 10 ) { $first_of_month_day_of_week_00 += 273; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30;
  13938         21503  
  13938         48671  
2325 41815 100       92626 if ( $_ == 11 ) { $first_of_month_day_of_week_00 += 304; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31;
  13938         20864  
  13938         51621  
2326 27877 100       74760 if ( $_ == 12 ) { $first_of_month_day_of_week_00 += 334; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30;
  13938         17918  
  13938         44525  
2327             }
2328             }
2329             }
2330             else
2331             {
2332 53560         91851 foreach ($month_num_12)
2333             {
2334             SWITCH:
2335             {
2336 53560 100       58013 if ( $_ == 2 ) { $first_of_month_day_of_week_00 += 31; last SWITCH; }
  53560         118563  
  4464         6116  
  4464         12092  
2337 49096 100       91191 if ( $_ == 3 ) { $first_of_month_day_of_week_00 += 60; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29;
  4463         5553  
  4463         11691  
2338 44633 100       88533 if ( $_ == 4 ) { $first_of_month_day_of_week_00 += 91; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31;
  4463         5353  
  4463         12043  
2339 40170 100       101365 if ( $_ == 5 ) { $first_of_month_day_of_week_00 += 121; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30;
  4463         5544  
  4463         14037  
2340 35707 100       69802 if ( $_ == 6 ) { $first_of_month_day_of_week_00 += 152; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30 + 31;
  4463         5839  
  4463         12484  
2341 31244 100       60620 if ( $_ == 7 ) { $first_of_month_day_of_week_00 += 182; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30 + 31 + 30;
  4463         5707  
  4463         12142  
2342 26781 100       70280 if ( $_ == 8 ) { $first_of_month_day_of_week_00 += 213; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30 + 31 + 30 + 31;
  4464         6578  
  4464         23503  
2343 22317 100       57474 if ( $_ == 9 ) { $first_of_month_day_of_week_00 += 244; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31;
  4463         9337  
  4463         12183  
2344 17854 100       39633 if ( $_ == 10 ) { $first_of_month_day_of_week_00 += 274; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30;
  4463         6124  
  4463         11901  
2345 13391 100       27669 if ( $_ == 11 ) { $first_of_month_day_of_week_00 += 305; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31;
  4463         5891  
  4463         12178  
2346 8928 100       24892 if ( $_ == 12 ) { $first_of_month_day_of_week_00 += 335; last SWITCH; } # $first_of_month_day_of_week_00 += 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30;
  4464         7372  
  4464         12911  
2347             }
2348             }
2349             }
2350              
2351              
2352             # Map day of week to 0-6
2353 220822         388578 $first_of_month_day_of_week_00 %= 7;
2354              
2355             # Map day of week '0' to '7'
2356 220822 100       460394 if ( $first_of_month_day_of_week_00 == 0 )
2357             {
2358 31650         41304 $first_of_month_day_of_week_00 = 7;
2359             }
2360              
2361 220822         5148127 return ( $first_of_month_day_of_week_00 );
2362             }
2363              
2364              
2365              
2366              
2367             ###############################################################################
2368             # Usage : Function is overloaded to accept one of two date input types
2369             # : 1) Date string
2370             # : get_numeric_day_of_week( SCALAR )
2371             # : 2) Month, dayofmonth, year
2372             # : get_numeric_day_of_week( SCALAR, SCALAR, SCALAR )
2373             # Purpose : get numeric day of week (1-7) for given date
2374             # Returns : - day of week number if successful
2375             # Parameters : 1) ( date string in any format )
2376             # : OR
2377             # : 2) ( month, day of month, year )
2378             # Throws : Throws exception for any invalid input
2379             # Comments : - Handles all years, even negative years (aka BC)
2380             # : - <1 for Mon ... 7 for Sun>
2381             # See Also : N/A
2382             ###############################################################################
2383             sub get_numeric_day_of_week
2384             {
2385              
2386              
2387             # Incoming Inspection
2388 15243 100 100 15243 1 87225 ( ( @_ == 1 ) || ( @_ == 3 ) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Should have either a date string, or a list of month,dayofmonth,year. '@_'.\n\n\n";
  2         237  
2389              
2390              
2391 15241         19051 my ( $month_input_10, $day_of_month_in_02, $year_in_06, $day_of_week_12 );
2392             # Parsing date string and is recursive one time into this function
2393 15241 100       36956 if ( @_ == 1 )
2394             {
2395 219 100       825 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string. '$_[0]'.\n\n\n";
  2         260  
2396 217 100       626 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$_[0]'.\n\n\n";
  1         97  
2397              
2398 216         544 ($month_input_10, $day_of_month_in_02, $year_in_06, $day_of_week_12 ) = date_only_parse($_[0]);
2399 216 100       718 if ( $day_of_week_12 )
2400             {
2401 215         514 return ( $day_of_week_12 );
2402             }
2403             else
2404             {
2405 1         4 croak "\n\n ($0) '${\(caller(0))[3]}' date string, '$_[0]', cannot be parsed.\n\n\n";
  1         105  
2406             }
2407             }
2408             # Individual date components
2409             else
2410             {
2411 15022 100       40444 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the month '$_[0]'.\n\n\n";
  1         150  
2412 15021 100       35965 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the month '$_[0]'.\n\n\n";
  1         160  
2413 15020 100       37813 ( is_valid_month($_[0]) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a valid month '$_[0]'.\n\n\n";
  3         483  
2414              
2415 15017 100       39385 ( ref(\$_[2]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the year number '$_[2]'.\n\n\n";
  1         160  
2416 15016 100       39675 ( $_[2] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the year number '$_[2]'.\n\n\n";
  1         123  
2417 15015 100       32708 ( is_valid_year($_[2]) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the year number '$_[2]'.\n\n\n";
  1         141  
2418              
2419 15014 100       36764 ( ref(\$_[1]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the day of month '$_[1]'.\n\n\n";
  1         143  
2420 15013 100       34012 ( $_[1] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the day of month '$_[1]'.\n\n\n";
  1         163  
2421 15012 100       37927 ( is_valid_day_of_month($_[0], $_[1], $_[2]) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value for the day of month (1-31) '$_[1]'.\n\n\n";
  16         2446  
2422              
2423 14996         78335 ($month_input_10, $day_of_month_in_02, $year_in_06 ) = ( $_[0], $_[1], $_[2] );
2424             }
2425              
2426              
2427 14996         33198 my $month_num_14 = set_month_to_month_number($month_input_10);
2428 14996         40369 my $year_phase_03 = get_year_phase( $year_in_06 );
2429              
2430 14996         76867 my $first_of_month_day_of_week_02 = $NUMERIC_DAY_OF_WEEK_ON_FIRST_OF_MONTH{$year_phase_03}{$month_num_14} + $day_of_month_in_02 - 1;
2431 14996         201584 $first_of_month_day_of_week_02 %= 7;
2432              
2433             # Map day of week to 0-6
2434 14996         20013 $first_of_month_day_of_week_02 %= 7;
2435              
2436             # Map day of week '0' to '7'
2437 14996 100       29940 if ( $first_of_month_day_of_week_02 == 0 )
2438             {
2439 1440         2093 $first_of_month_day_of_week_02 = 7;
2440             }
2441              
2442 14996         50372 return ( $first_of_month_day_of_week_02 );
2443             }
2444              
2445              
2446              
2447              
2448             ###############################################################################
2449             # Usage : get_month_from_string( SCALAR )
2450             # Purpose : extract month from given date string
2451             # Returns : month number if successful
2452             # Parameters : date string in any format
2453             # Throws : Throws exception for any invalid input
2454             # Comments : - Handles all years, even negative years (aka BC)
2455             # : - 1 for Jan ... 12 for Dec
2456             # See Also : N/A
2457             ###############################################################################
2458             sub get_month_from_string
2459             {
2460              
2461              
2462             # Incoming Inspection
2463 40 100   40 1 15031 ( @_ == 1 ) or croak "\n\n ($0) '${\(caller(0))[3]}' Should have a date string to be parsed. '@_'.\n\n\n";
  28         3932  
2464              
2465 12 100       42 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string. '$_[0]'.\n\n\n";
  2         214  
2466 10 100       28 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$_[0]'.\n\n\n";
  1         160  
2467              
2468              
2469 9         22 my ($month_input_15, $day_of_month_15, $year_15, $day_of_week_15) = date_only_parse( $_[0] );
2470 9 100       30 if ( $month_input_15 eq '' )
2471             {
2472 1         4 croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date string '$_[0]'.\n\n\n";
  1         173  
2473             }
2474             else
2475             {
2476 8         39 return ( $month_input_15 );
2477             }
2478              
2479             }
2480              
2481              
2482              
2483              
2484             ###############################################################################
2485             # Usage : get_dayofmonth_from_string( SCALAR )
2486             # Purpose : extract day of month from given date string
2487             # Returns : day of month if successful
2488             # Parameters : date string in any format
2489             # Throws : Throws exception for any invalid input
2490             # Comments : - Handles all years, even negative years (aka BC)
2491             # See Also : N/A
2492             ###############################################################################
2493             sub get_dayofmonth_from_string
2494             {
2495              
2496              
2497             # Incoming Inspection
2498 40 100   40 1 16381 ( @_ == 1 ) or croak "\n\n ($0) '${\(caller(0))[3]}' Should have a date string to be parsed. '@_'.\n\n\n";
  28         4055  
2499              
2500 12 100       43 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string. '$_[0]'.\n\n\n";
  2         241  
2501 10 100       28 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$_[0]'.\n\n\n";
  1         122  
2502              
2503              
2504 9         28 my ($month_input_18, $day_of_month_18, $year_18, $day_of_week_18) = date_only_parse( $_[0] );
2505 9 100       30 if ( !(defined ($day_of_month_18) ) )
2506             {
2507 1         5 croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date string '$_[0]'.\n\n\n";
  1         133  
2508             }
2509             else
2510             {
2511 8         44 return ( $day_of_month_18 );
2512             }
2513              
2514             }
2515              
2516              
2517              
2518              
2519             ###############################################################################
2520             # Usage : get_year_from_string( SCALAR )
2521             # Purpose : extract year from given date string
2522             # Returns : year if successful
2523             # Parameters : date string in any format
2524             # Throws : Throws exception for any invalid input
2525             # Comments : - Handles all years, even negative years (aka BC)
2526             # See Also : N/A
2527             ###############################################################################
2528             sub get_year_from_string
2529             {
2530              
2531              
2532             # Incoming Inspection
2533 40 100   40 1 26156 ( @_ == 1 ) or croak "\n\n ($0) '${\(caller(0))[3]}' Should have a date string to be parsed. '@_'.\n\n\n";
  28         9622  
2534              
2535 12 100       50 ( ref(\$_[0]) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string. '$_[0]'.\n\n\n";
  2         317  
2536 10 100       34 ( $_[0] ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$_[0]'.\n\n\n";
  1         444  
2537              
2538              
2539 9         32 my ($month_input_14, $day_of_month_14, $year_14, $day_of_week_14) = date_only_parse( $_[0] );
2540 9 100       32 if ( !(defined ($year_14) ) )
2541             {
2542 1         7 croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date string '$_[0]'.\n\n\n";
  1         178  
2543             }
2544             else
2545             {
2546 8         39 return ( $year_14 );
2547             }
2548              
2549             }
2550              
2551              
2552              
2553              
2554             ###############################################################################
2555             # Usage : compare_year1_and_year2( SCALAR, SCALAR )
2556             # Purpose : compares two dates to find which one is the later year, months and days are ignored
2557             # Returns : - '1' if the FIRST year is LATER than the second
2558             # : - '-1' if the FIRST year is EARLIER than the second
2559             # : - '0' if both years are the same
2560             # Parameters : (
2561             # : date ONE in any format,
2562             # : date TWO in any format
2563             # : )
2564             # Throws : Throws exception for any invalid input
2565             # Comments : N/A
2566             # See Also : N/A
2567             ###############################################################################
2568             sub compare_year1_and_year2
2569             {
2570             my (
2571 30     30 1 18243 $date_one_03,
2572             $date_two_03
2573             )
2574             = @_;
2575              
2576              
2577             # Incoming Inspection
2578 30         57 my $num_input_params_30 = 2;
2579 30 100       127 ( @_ == $num_input_params_30) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_30 parameters ('date1' and date2). '@_'.\n\n\n";
  8         1307  
2580              
2581 22 100       91 ( ref(\$date_one_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR first parameter for the first date '$date_one_03'.\n\n\n";
  1         130  
2582 21 100       77 ( ref(\$date_two_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR second parameter for the second date '$date_two_03'.\n\n\n";
  1         127  
2583              
2584 20 100       65 ( $date_one_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the first date '$date_one_03'.\n\n\n";
  1         120  
2585 19 100       57 ( $date_two_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the second date '$date_two_03'.\n\n\n";
  1         119  
2586              
2587 18 100       45 ( date_only_parse($date_one_03) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date1 string '$date_one_03'.\n\n\n";
  1         145  
2588 17 100       36 ( date_only_parse($date_two_03) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date2 string '$date_two_03'.\n\n\n";
  1         184  
2589              
2590              
2591 16         46 my ( $date1_month_num_06, $date1_day_of_month_06, $date1_year_num_06, $date1_day_of_week_06 ) = date_only_parse($date_one_03);
2592 16         123 my ( $date2_month_num_06, $date2_day_of_month_06, $date2_year_num_06, $date2_day_of_week_06 ) = date_only_parse($date_two_03);
2593              
2594 16 100       68 if ( $date1_year_num_06 == $date2_year_num_06 )
    100          
2595             {
2596 4         33 return ( '0' );
2597             }
2598             elsif ( $date1_year_num_06 > $date2_year_num_06 )
2599             {
2600 5         41 return ( '1' );
2601             }
2602             else
2603             {
2604 7         54 return ( '-1' );
2605             }
2606              
2607             }
2608              
2609              
2610              
2611              
2612             ###############################################################################
2613             # Usage : year1_to_year2_delta( SCALAR, SCALAR )
2614             # Purpose : calculates the difference in WHOLE years between two dates (basically it truncates the date difference to whole years)
2615             # Returns : integer year difference if successful
2616             # Parameters : (
2617             # : date ONE in any format,
2618             # : date TWO in any format
2619             # : )
2620             # Throws : Throws exception for any invalid input
2621             # Comments : - Difference is positive if date1 > date2
2622             # : - Difference is negative if date1 < date2
2623             # : - Examples Date1 = 4/5/1977 and Date2 = 11/16/1975 equals ONE complete year difference
2624             # See Also : N/A
2625             ###############################################################################
2626             sub year1_to_year2_delta
2627             {
2628             my (
2629 57     57 1 8503 $date_one_04,
2630             $date_two_04
2631             )
2632             = @_;
2633              
2634              
2635             # Incoming Inspection
2636 57         107 my $num_input_params_31 = 2;
2637 57 100       185 ( @_ == $num_input_params_31) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_31 parameters ('date1' and date2). '@_'.\n\n\n";
  8         1136  
2638              
2639 49 100       195 ( ref(\$date_one_04) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR first parameter for the first date '$date_one_04'.\n\n\n";
  1         126  
2640 48 100       169 ( ref(\$date_two_04) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR second parameter for the second date '$date_two_04'.\n\n\n";
  1         122  
2641              
2642 47 100       126 ( $date_one_04 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the first date '$date_one_04'.\n\n\n";
  1         128  
2643 46 100       112 ( $date_two_04 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the second date '$date_two_04'.\n\n\n";
  1         372  
2644              
2645 45 100       104 ( date_only_parse($date_one_04) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date1 string '$date_one_04'.\n\n\n";
  1         141  
2646 44 100       92 ( date_only_parse($date_two_04) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date2 string '$date_two_04'.\n\n\n";
  1         158  
2647              
2648              
2649 43         100 my ( $date1_month_num_07, $date1_day_of_month_07, $date1_year_num_07, $date1_day_of_week_07 ) = date_only_parse($date_one_04);
2650 43         115 my ( $date2_month_num_07, $date2_day_of_month_07, $date2_year_num_07, $date2_day_of_week_07 ) = date_only_parse($date_two_04);
2651              
2652 43         81 my $year_difference_00;
2653 43 100       107 if ( $date1_year_num_07 == $date2_year_num_07 )
2654             {
2655 3         7 $year_difference_00 = '0';
2656             }
2657             else
2658             {
2659 40         60 $year_difference_00 = $date1_year_num_07 - $date2_year_num_07;
2660             }
2661              
2662              
2663 43         85 $date1_month_num_07 = set_month_to_month_number($date1_month_num_07);
2664 43         102 $date2_month_num_07 = set_month_to_month_number($date2_month_num_07);
2665              
2666              
2667 43         92 my $date1_is_leap_year = 'no';
2668 43 100       105 if ( is_leap_year($date1_year_num_07) )
2669             {
2670 21         34 $date1_is_leap_year = 'yes';
2671             }
2672              
2673 43         71 my $date2_is_leap_year = 'no';
2674 43 100       83 if ( is_leap_year($date2_year_num_07) )
2675             {
2676 19         31 $date2_is_leap_year = 'yes';
2677             }
2678              
2679              
2680 43 100       139 if ( $year_difference_00 > 0 )
    100          
2681             {
2682 18 100 100     111 if ( $date1_month_num_07 < $date2_month_num_07 )
    100          
2683             {
2684 1         4 $year_difference_00--;
2685             }
2686             elsif ( ( $date1_month_num_07 == $date2_month_num_07 ) && ( $date1_day_of_month_07 < $date2_day_of_month_07 ) )
2687             {
2688 3         6 $year_difference_00--;
2689             }
2690              
2691             # Leap Year Adjustments
2692             # whole year whole year
2693             # Date1 Date2 current fix
2694             # 28 28 YES YES
2695             # 28 28(9) YES YES
2696             # 28 29 no YES (to be adjusted UP)
2697             # 28(9) 28 YES no (to be adjusted DOWN)
2698             # 28(9) 28(9) YES YES
2699             # 28(9) 29 no no
2700             # 29 28 YES YES
2701             # 29 28(9) YES YES
2702             # 29 29 YES YES
2703 18 100 100     130 if ( ( $date1_is_leap_year eq 'no' ) && ( $date2_is_leap_year eq 'yes' ) )
    100 100        
2704             {
2705 4 100 100     20 if ( ( $date1_day_of_month_07 == 28 ) && ( $date2_day_of_month_07 == 29 ) )
2706             {
2707 1         3 $year_difference_00++;
2708             }
2709             }
2710             elsif ( ( $date1_is_leap_year eq 'yes' ) && ( $date2_is_leap_year eq 'no' ) )
2711             {
2712 4 100 100     22 if ( ( $date1_day_of_month_07 == 28 ) && ( $date2_day_of_month_07 == 28 ) )
2713             {
2714 1         3 $year_difference_00--;
2715             }
2716             }
2717             }
2718             elsif ( $year_difference_00 < 0 )
2719             {
2720 22 100 100     127 if ( $date1_month_num_07 > $date2_month_num_07 )
    100          
2721             {
2722 3         7 $year_difference_00++;
2723             }
2724             elsif ( ( $date1_month_num_07 == $date2_month_num_07 ) && ( $date1_day_of_month_07 > $date2_day_of_month_07 ) )
2725             {
2726 5         11 $year_difference_00++;
2727             }
2728              
2729             # Leap Year Adjustments
2730             # whole year whole year
2731             # Date1 Date2 current fix
2732             # 28 28 YES YES
2733             # 28 28(9) YES no (to be adjusted UP)
2734             # 28 29 YES YES
2735             # 28(9) 28 YES YES
2736             # 28(9) 28(9) YES YES
2737             # 28(9) 29 YES YES
2738             # 29 28 no YES (to be adjusted DOWN)
2739             # 29 28(9) no no
2740             # 29 29 YES YES
2741 22 100 100     156 if ( ( $date1_is_leap_year eq 'no' ) && ( $date2_is_leap_year eq 'yes' ) )
    100 100        
2742             {
2743 5 100 100     35 if ( ( $date1_day_of_month_07 == 28 ) && ( $date2_day_of_month_07 == 28 ) )
2744             {
2745 1         3 $year_difference_00++;
2746             }
2747             }
2748             elsif ( ( $date1_is_leap_year eq 'yes' ) && ( $date2_is_leap_year eq 'no' ) )
2749             {
2750 7 100 100     33 if ( ( $date1_day_of_month_07 == 29 ) && ( $date2_day_of_month_07 == 28 ) )
2751             {
2752 1         2 $year_difference_00--;
2753             }
2754             }
2755             }
2756              
2757             # Set year difference to string '0' if it is zero
2758 43 100       102 if ( $year_difference_00 == 0 )
2759             {
2760 10         13 $year_difference_00 = '0';
2761             }
2762              
2763 43         315 return( $year_difference_00 );
2764             }
2765              
2766              
2767              
2768              
2769             ###############################################################################
2770             # Usage : date_offset_in_years( SCALAR, SCALAR )
2771             # Purpose : find a date in the future or past offset by the number of YEARS from the given date
2772             # Returns : - date of the day offset from the given date if successful
2773             # Parameters : (
2774             # : date in any format,
2775             # : number of WHOLE offset years, positive is future date, negative is past date, zero is current date (no offset)
2776             # : )
2777             # Throws : Throws exception for any invalid input
2778             # Comments : There are two exceptions where the new month/dayofmonth do NOT match the original
2779             # : - Feb 29 in a leap year maps to Feb 28 in a NON leap year
2780             # : - Feb 28 in a NON leap year maps to Feb 29 in a leap year
2781             # See Also : N/A
2782             ###############################################################################
2783             sub date_offset_in_years
2784             {
2785             my (
2786 34     34 1 11697 $date_in_03,
2787             $date_delta_years_00
2788             )
2789             = @_;
2790              
2791              
2792             # Incoming Inspection
2793 34         69 my $num_input_params_32 = 2;
2794 34 100       135 ( @_ == $num_input_params_32) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_32 parameter(s), a date string followed by the number of offset days. '@_'.\n\n\n";
  3         1945  
2795              
2796 31 100       130 ( ref(\$date_in_03) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string '$date_in_03'.\n\n\n";
  1         128  
2797 30 100       104 ( $date_in_03 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$date_in_03'.\n\n\n";
  1         155  
2798 29 100       88 ( date_only_parse($date_in_03) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot parse the date from the input date string '$date_in_03'.\n\n\n";
  2         357  
2799              
2800 27 100       94 ( ref(\$date_delta_years_00) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the number of WHOLE offset years '$date_delta_years_00'.\n\n\n";
  1         150  
2801 26 100       219 ( $date_delta_years_00 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the number of WHOLE offset years '$date_delta_years_00'.\n\n\n";
  1         175  
2802 25 100       124 ( $date_delta_years_00 =~ m/^\-{0,1}\d+$/ ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the number of WHOLE offset years '$date_delta_years_00'.\n\n\n";
  1         207  
2803              
2804              
2805 24 100       65 if ( $date_delta_years_00 == 0 )
2806             {
2807 1         5 return ( format_date( $date_in_03 ) );
2808             }
2809              
2810              
2811 23         54 my ( $date1_month_num_08, $date1_day_of_month_08, $date1_year_num_08, $date1_day_of_week_08 ) = date_only_parse($date_in_03);
2812              
2813              
2814 23         64 my $offset_year_01 = $date1_year_num_08 + $date_delta_years_00;
2815              
2816             # Handle case where leap year (Feb 29) is to be mapped to a NON leap year (Feb 28)
2817 23         40 my $mapped_to_end_of_month = $date1_day_of_month_08;
2818 23 100       61 if ( !is_leap_year( $offset_year_01 ) )
    100          
2819             {
2820 14 100 100     74 if ( ( $date1_month_num_08 == 2 ) && ( $date1_day_of_month_08 == 29 ) )
2821             {
2822 2         5 $mapped_to_end_of_month = 28;
2823             }
2824             }
2825              
2826             # Handle case where NON leap year (Feb 28) is to be mapped to a leap year (Feb 29)
2827             elsif ( !is_leap_year( $date1_year_num_08 ) )
2828             {
2829 5 100 100     33 if ( ( $date1_month_num_08 == 2 ) && ( $date1_day_of_month_08 == 28 ) )
2830             {
2831 2         5 $mapped_to_end_of_month = 29;
2832             }
2833             }
2834              
2835 23         94 return( format_date( $date1_month_num_08, $mapped_to_end_of_month, $offset_year_01 ) );
2836             }
2837              
2838              
2839              
2840              
2841             ###############################################################################
2842             # Usage : number_of_weekdays_in_range( SCALAR, SCALAR )
2843             # Purpose : calculates the number of weekdays in the range of the two dates
2844             # Returns : integer number of weekdays if successful
2845             # Parameters : (
2846             # : date ONE in any format,
2847             # : date TWO in any format
2848             # : )
2849             # Throws : Throws exception for any invalid input
2850             # Comments : - Difference is positive if date1 > date2
2851             # : - Difference is negative if date1 < date2
2852             # : - Friday to Saturday counts as ZERO days
2853             # : - Friday to Sunday counts as ZERO days
2854             # : - Friday to Monday counts as one day
2855             # : - Tuesday to previous Wednesday counts as NEGATIVE four days
2856             # See Also : N/A
2857             ###############################################################################
2858             sub number_of_weekdays_in_range
2859             {
2860             my (
2861 73     73 1 5766 $date_one_05,
2862             $date_two_05
2863             )
2864             = @_;
2865              
2866              
2867             # Incoming Inspection
2868 73         139 my $num_input_params_33 = 2;
2869 73 100       270 ( @_ == $num_input_params_33) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_33 parameters ('date1' and date2). '@_'.\n\n\n";
  8         1106  
2870              
2871 65 100       270 ( ref(\$date_one_05) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR first parameter for the first date '$date_one_05'.\n\n\n";
  1         116  
2872 64 100       231 ( ref(\$date_two_05) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR second parameter for the second date '$date_two_05'.\n\n\n";
  1         123  
2873              
2874 63 100       191 ( $date_one_05 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the first date '$date_one_05'.\n\n\n";
  1         126  
2875 62 100       178 ( $date_two_05 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the second date '$date_two_05'.\n\n\n";
  1         130  
2876              
2877 61 100       164 ( date_only_parse($date_one_05) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date1 string '$date_one_05'.\n\n\n";
  1         138  
2878 60 100       119 ( date_only_parse($date_two_05) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot extract the date from the input date2 string '$date_two_05'.\n\n\n";
  1         160  
2879              
2880              
2881             # Get count of ALL days in range as a starting point
2882 59         188 my $number_of_days_in_range_00 = date1_to_date2_delta( $date_one_05, $date_two_05 );
2883              
2884             # Get the number of weekdays in the range for the WHOLE weeks in the range
2885 59         239 my $number_weekdays_00 = int( abs($number_of_days_in_range_00) / 7 ) * 5;
2886              
2887             # Get the remainder of weekdays in the range that is discarded by the previous variable
2888 59         116 my $week_remainder_00 = abs( $number_of_days_in_range_00 ) % 7;
2889              
2890 59         159 my $current_dayofweek_00 = get_numeric_day_of_week($date_two_05);
2891             # Cycle through the left over days in the range that do not form a WHOLE week and add them in into the total IF they are weekdays
2892 59         274 for ( my $iii_004=0; $iii_004<$week_remainder_00; $iii_004++ )
2893             {
2894 139 100       268 if ( $number_of_days_in_range_00 > 0 ) # range is positive
2895             {
2896 76         97 $current_dayofweek_00++;
2897 76 100       155 if ( $current_dayofweek_00 > 7 )
2898             {
2899 20         27 $current_dayofweek_00 -= 7;
2900             }
2901              
2902 76 100       171 if ( $current_dayofweek_00 < 6 ) # weekdays
2903             {
2904 42         56 $number_weekdays_00++;
2905             }
2906             }
2907 139 100       342 if ( $number_of_days_in_range_00 < 0 ) # range is negative
2908             {
2909 63         63 $current_dayofweek_00--;
2910 63 100       106 if ( $current_dayofweek_00 < 1 )
2911             {
2912 4         11 $current_dayofweek_00 += 7;
2913             }
2914              
2915 63 100       140 if ( $current_dayofweek_00 < 6 ) # weekdays
2916             {
2917 54         117 $number_weekdays_00++;
2918             }
2919             }
2920             }
2921              
2922              
2923             # Put correct sign to number of days in range
2924 59 100       186 if ( $number_of_days_in_range_00 > 0 )
    100          
2925             {
2926 32         289 return( $number_weekdays_00 );
2927             }
2928             elsif ( $number_of_days_in_range_00 < 0 )
2929             {
2930 24         255 return( -$number_weekdays_00 );
2931             }
2932             else
2933             {
2934 3         28 return( '0' );
2935             }
2936              
2937             }
2938              
2939              
2940              
2941              
2942             ###############################################################################
2943             # Usage : date_offset_in_weekdays( SCALAR, SCALAR )
2944             # Purpose : find a WEEKDAY date in the future or past offset by the number of weekdays from the given starting WEEKDAY date
2945             # Returns : - date of the WEEKDAY day offset from the given WEEKDAY date if successful
2946             # Parameters : (
2947             # : WEEKDAY date in any format,
2948             # : number of weekdays offset, positive is future date, negative is past date, zero is current date (no offset)
2949             # : )
2950             # Throws : Throws exception for any invalid input INCLUDING weekend dates
2951             # Comments : This effectively functions as if ALL weekend dates were removed
2952             # : from the calendar. This function accepts ONLY weekday dates and
2953             # : outputs ONLY weekday dates
2954             # See Also : N/A
2955             ###############################################################################
2956             sub date_offset_in_weekdays
2957             {
2958             my (
2959 91     91 1 9487 $date_in_05,
2960             $date_delta_01
2961             )
2962             = @_;
2963              
2964              
2965             # Incoming Inspection
2966 91         181 my $num_input_params_36 = 2;
2967 91 100       453 ( @_ == $num_input_params_36) or croak "\n\n ($0) '${\(caller(0))[3]}' should have exactly $num_input_params_36 parameter(s), a date string followed by the number of offset days. '@_'.\n\n\n";
  6         807  
2968              
2969 85 100       483 ( ref(\$date_in_05) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the date string '$date_in_05'.\n\n\n";
  1         115  
2970 84 100       295 ( $date_in_05 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty string for the date string '$date_in_05'.\n\n\n";
  1         132  
2971 83 100       229 ( date_only_parse($date_in_05) ) or croak "\n\n ($0) '${\(caller(0))[3]}' Cannot parse the date from the input date string '$date_in_05'.\n\n\n";
  3         441  
2972              
2973 80 100       318 ( ref(\$date_delta_01) eq 'SCALAR' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a SCALAR parameter for the number of offset days '$date_delta_01'.\n\n\n";
  1         155  
2974 79 100       253 ( $date_delta_01 ne '' ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects a NON-empty value for the number of offset days '$date_delta_01'.\n\n\n";
  1         170  
2975 78 100       416 ( $date_delta_01 =~ m/^\-{0,1}\d+$/ ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects an integer value, positive, negative or zero, for the number of offset days '$date_delta_01'.\n\n\n";
  1         239  
2976              
2977              
2978             # Check that starting date is a WEEKDAY
2979 77         242 my $day_of_week_16 = get_numeric_day_of_week($date_in_05);
2980              
2981 77 100       270 ( $day_of_week_16 < 6 ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects the starting date, '$date_in_05', to be a WEEKDAY. It is incorrectly a ${\(set_day_to_day_name_full($day_of_week_16))}.\n\n\n";
  1         9  
  1         4  
2982              
2983 76         121 my $past_future = 1;
2984 76 100       234 if ( $date_delta_01 < 0 )
2985             {
2986 35         62 $past_future = -1;
2987             }
2988              
2989             # 1 0 0 7/5 2 0 0 7/5 3 0 0 7/5 4 0 0 7/5 5 0 0 7/5
2990             # 1 1 1 int(7/5) 2 1 1 int(7/5) 3 1 1 int(7/5) 4 1 1 int(7/5) 5 1 3 int(7/5) + 2
2991             # 1 2 2 int(7/5) 2 2 2 int(7/5) 3 2 2 int(7/5) 4 2 4 int(7/5) + 2 5 2 4 int(7/5) + 2
2992             # 1 3 3 int(7/5) - 1 2 3 3 int(7/5) - 1 3 3 5 int(7/5) + 1 4 3 5 int(7/5) + 1 5 3 5 int(7/5) + 1
2993             # 1 4 4 int(7/5) - 1 2 4 6 int(7/5) + 1 3 4 6 int(7/5) + 1 4 4 6 int(7/5) + 1 5 4 6 int(7/5) + 1
2994              
2995             # 1 0 0 7/5 2 0 0 7/5 3 0 0 7/5 4 0 0 7/5 5 0 0 7/5
2996             # 1 -1 -3 -int(abs(7/5)) - 2 2 -1 -1 -int(abs(7/5)) 3 -1 -1 -int(abs(7/5)) 4 -1 -1 -int(abs(7/5)) 5 -1 -1 -int(abs(7/5))
2997             # 1 -2 -4 -int(abs(7/5)) - 2 2 -2 -4 -int(abs(7/5)) - 2 3 -2 -2 -int(abs(7/5)) 4 -2 -2 -int(abs(7/5)) 5 -2 -2 -int(abs(7/5))
2998             # 1 -3 -5 -int(abs(7/5)) - 1 2 -3 -5 -int(abs(7/5)) - 1 3 -3 -5 -int(abs(7/5)) - 1 4 -3 -3 -int(abs(7/5)) + 1 5 -3 -3 -int(abs(7/5)) + 1
2999             # 1 -4 -6 -int(abs(7/5)) - 1 2 -4 -6 -int(abs(7/5)) - 1 3 -4 -6 -int(abs(7/5)) - 1 4 -4 -6 -int(abs(7/5)) - 1 5 -4 -4 -int(abs(7/5)) + 1
3000              
3001 76         167 my $weekday_remainder = abs($date_delta_01) % 5;
3002 76         122 my $num_days_effective = 'xxx';
3003 76 100 100     1583 if (
    100 100        
    100 66        
    100 100        
    100 100        
      66        
      100        
      100        
      66        
      100        
      100        
      66        
      100        
      100        
      66        
3004             ( ( $day_of_week_16 == 1 ) && ( $date_delta_01 > 0 ) ) ||
3005             ( ( $day_of_week_16 == 5 ) && ( $date_delta_01 < 0 ) )
3006             )
3007             {
3008 15         35 foreach ( $weekday_remainder )
3009             {
3010             SWITCH:
3011             {
3012 15 100       22 if ( $_ <= 2 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ); last SWITCH; }
  15         39  
  10         38  
  10         39  
3013 5         31 $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) - $past_future;
3014             }
3015             }
3016             }
3017             elsif (
3018             ( ( $day_of_week_16 == 2 ) && ( $date_delta_01 > 0 ) ) ||
3019             ( ( $day_of_week_16 == 4 ) && ( $date_delta_01 < 0 ) )
3020             )
3021             {
3022 14         42 foreach ( $weekday_remainder )
3023             {
3024             SWITCH:
3025             {
3026 14 100       23 if ( $_ <= 2 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ); last SWITCH; }
  14         38  
  10         35  
  10         45  
3027 4 100       14 if ( $_ == 3 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) - $past_future; last SWITCH; }
  2         8  
  2         10  
3028 2         13 $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) + $past_future;
3029             }
3030             }
3031             }
3032             elsif (
3033             ( ( $day_of_week_16 == 3 ) && ( $date_delta_01 > 0 ) ) ||
3034             ( ( $day_of_week_16 == 3 ) && ( $date_delta_01 < 0 ) )
3035             )
3036             {
3037 14         35 foreach ( $weekday_remainder )
3038             {
3039             SWITCH:
3040             {
3041 14 100       22 if ( $_ <= 2 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ); last SWITCH; }
  14         40  
  10         36  
  10         37  
3042 4         21 $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) + $past_future;
3043             }
3044             }
3045             }
3046             elsif (
3047             ( ( $day_of_week_16 == 4 ) && ( $date_delta_01 > 0 ) ) ||
3048             ( ( $day_of_week_16 == 2 ) && ( $date_delta_01 < 0 ) )
3049             )
3050             {
3051 14         35 foreach ( $weekday_remainder )
3052             {
3053             SWITCH:
3054             {
3055 14 100       27 if ( $_ < 2 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ); last SWITCH; }
  14         56  
  6         113  
  6         25  
3056 8 100       22 if ( $_ == 2 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) + $past_future * 2; last SWITCH; }
  4         15  
  4         16  
3057 4         24 $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) + $past_future;
3058             }
3059             }
3060             }
3061             elsif (
3062             ( ( $day_of_week_16 == 5 ) && ( $date_delta_01 > 0 ) ) ||
3063             ( ( $day_of_week_16 == 1 ) && ( $date_delta_01 < 0 ) )
3064             )
3065             {
3066 14         36 foreach ( $weekday_remainder )
3067             {
3068             SWITCH:
3069             {
3070 14 100       23 if ( $_ == 0 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ); last SWITCH; }
  14         42  
  2         9  
  2         9  
3071 12 100       31 if ( $_ == 1 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) + $past_future * 2; last SWITCH; }
  4         16  
  4         18  
3072 8 100       20 if ( $_ == 2 ) { $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) + $past_future * 2; last SWITCH; }
  4         13  
  4         14  
3073 4         22 $num_days_effective = $past_future * int( abs($date_delta_01 * (7/5) ) ) + $past_future;
3074             }
3075             }
3076             }
3077             else
3078             {
3079 5         15 $num_days_effective = 0;
3080             }
3081              
3082              
3083             # Check that offset date is a WEEKDAY
3084 76         301 my $weekday_offset_00 = date_offset_in_days($date_in_05, $num_days_effective);
3085 76         241 my $day_of_week_17 = get_numeric_day_of_week($weekday_offset_00);
3086              
3087 76 50       320 ( $day_of_week_17 < 6 ) or croak "\n\n ($0) '${\(caller(0))[3]}' Expects the offset date, '$weekday_offset_00', to be a WEEKDAY. It is incorrectly a ${\(set_day_to_day_name_full($day_of_week_17))}. This condition should NOT occur. Something is amiss.\n\n\n";
  0         0  
  0         0  
3088              
3089 76         962 return ( $weekday_offset_00 );
3090             }
3091              
3092              
3093              
3094              
3095             }
3096             1;
3097              
3098             __END__