File Coverage

blib/lib/Date/Hijri.pm
Criterion Covered Total %
statement 49 54 90.7
branch 6 10 60.0
condition 4 9 44.4
subroutine 12 13 92.3
pod 0 9 0.0
total 71 95 74.7


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             ############################################################
4             # Date::Hijri
5             # module for converting islamic (hijri) and gregorian dates
6             # (c) zeitform Internet Dienste 2003 - alex@zeitform.de
7             # This program is free software; you can redistribute it and/or
8             # modify it under the same terms as Perl itself.
9             #
10             # based on kcalendarsystemhijri.cpp
11             # Copyright (c) 2002-2003 Carlos Moro
12             # Copyright (c) 2002-2003 Hans Petter Bieker
13             #
14             # This library is free software; you can redistribute it and/or
15             # modify it under the terms of the GNU Library General Public
16             # License as published by the Free Software Foundation; either
17             # version 2 of the License, or (at your option) any later version.
18             #
19             # This library is distributed in the hope that it will be useful,
20             # but WITHOUT ANY WARRANTY; without even the implied warranty of
21             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22             # Library General Public License for more details.
23             #
24             # You should have received a copy of the GNU Library General Public License
25             # along with this library; see the file COPYING.LIB. If not, write to
26             # the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
27             # Boston, MA 02111-1307, USA.
28             #
29             # kcalendarsystemhijri.cpp
30             # [...] is translated from the Lisp code
31             # in ``Calendrical Calculations'' by Nachum Dershowitz and
32             # Edward M. Reingold, Software---Practice & Experience,
33             # vol. 20, no. 9 (September, 1990), pp. 899--928.
34             #
35             # This code is in the public domain, but any use of it
36             # should publically acknowledge its source.
37             #
38             # Example usage:
39             #
40             # use Date::Hijri;
41             #
42             # print join("-", g2h(22,8,2003)); # prints 23-6-1424
43             # print join("-", h2g(23,6,1424)); # prints 22-8-2003
44             #
45             ############################################################
46              
47             package Date::Hijri;
48 1     1   45710 use strict;
  1         3  
  1         38  
49 1     1   5 use warnings;
  1         2  
  1         33  
50 1     1   5 use vars qw($VERSION @ISA @EXPORT);
  1         6  
  1         130  
51             require Exporter;
52              
53             @ISA = qw(Exporter);
54             @EXPORT = qw(h2g g2h);
55              
56             $VERSION = '0.02';
57              
58             ############################################################
59              
60 1     1   5 use constant IslamicEpoch => 227014;
  1         2  
  1         933  
61              
62             ############################################################
63              
64             sub g2h
65             {
66 1     1 0 9 my ($day, $month, $year) = @_;
67 1         8 return Absolute2Islamic(Gregorian2Absolute($day, $month, $year));
68             }
69              
70             sub h2g
71             {
72 1     1 0 20 my ($day, $month, $year) = @_;
73 1         9 return Absolute2Gregorian(Islamic2Absolute($day, $month, $year));
74             }
75              
76             sub lastDayOfGregorianMonth
77             {
78             # Compute the last date of the month for the Gregorian calendar.
79 50     50 0 50 my ($month, $year) = @_;
80 50 100       82 if ($month == 2)
81             {
82 9 50 33     49 return 29 if ($year % 4 == 0 && $year % 100 != 0) || ($year % 400 == 0);
      33        
83             }
84 50         128 return (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[$month - 1];
85             }
86              
87             sub Gregorian2Absolute
88             {
89             # Computes the absolute date from the Gregorian date.
90 16     16 0 19 my ($day, $month, $year) = @_;
91 16         17 my $N = $day; # days this month
92 16         34 for (my $m = $month - 1; $m > 0; $m--) # days in prior months this year
93             {
94 42         66 $N += lastDayOfGregorianMonth($m, $year);
95             }
96 16         66 return int($N # days this year
97             + 365 * ($year - 1) # days in previous years ignoring leap days
98             + ($year - 1) / 4 # Julian leap days before this year...
99             - ($year - 1) / 100 # ...minus prior century years...
100             + ($year - 1) / 400); # ...plus prior years divisible by 400
101             }
102              
103             sub Absolute2Gregorian
104             {
105             # Computes the Gregorian date from the absolute date.
106 1     1 0 2 my ($d) = @_;
107             # Search forward year by year from approximate year
108 1         2 my $year = int($d / 366 + 0.5);
109 1         4 while ($d >= Gregorian2Absolute(1,1,$year+1)) { $year++; }
  5         10  
110             # Search forward month by month from January
111 1         3 my $month = 1;
112 1         3 while ($d > Gregorian2Absolute(lastDayOfGregorianMonth($month, $year), $month, $year)) { $month++; }
  7         12  
113 1         4 my $day = $d - Gregorian2Absolute(1, $month, $year) + 1;
114              
115 1         7 return ($day, $month, $year);
116             }
117              
118             sub IslamicLeapYear
119             {
120             # True if year is an Islamic leap year
121 0     0 0 0 my ($year) = @_;
122 0 0       0 return ((((11 * $year) + 14) % 30) < 11) ? 1 : 0;
123             }
124              
125             sub lastDayOfIslamicMonth
126             {
127             # Last day in month during year on the Islamic calendar.
128 6     6 0 7 my ($month, $year) = @_;
129 6 100 66     25 return ($month % 2 == 1) || ($month == 12 && IslamicLeapYear($year)) ? 30 : 29;
130             }
131              
132             sub Islamic2Absolute
133             {
134             # Computes the absolute date from the Islamic date.
135 13     13 0 14 my ($day, $month, $year) = @_;
136 13         49 return int($day # days so far this month
137             + 29 * ($month - 1) # days so far...
138             + int($month /2) # ...this year
139             + 354 * ($year - 1) # non-leap days in prior years
140             + (3 + (11 * $year)) / 30 # leap days in prior years
141             + IslamicEpoch); # days before start of calendar
142             }
143              
144             sub Absolute2Islamic
145             {
146             # Computes the Islamic date from the absolute date.
147 1     1 0 2 my ($d) = @_;
148 1         2 my ($day, $month, $year);
149 1 50       3 if ($d <= IslamicEpoch)
150             {
151             # Date is pre-Islamic
152 0         0 $month = 0;
153 0         0 $day = 0;
154 0         0 $year = 0;
155             }
156             else
157             {
158             # Search forward year by year from approximate year
159 1         3 $year = int(($d - IslamicEpoch) / 355);
160 1         5 while ($d >= Islamic2Absolute(1,1,$year+1)) { $year++; }
  4         9  
161             # Search forward month by month from Muharram
162 1         2 $month = 1;
163 1         4 while ($d > Islamic2Absolute(lastDayOfIslamicMonth($month,$year), $month, $year)) { $month++ }
  5         9  
164 1         4 $day = $d - Islamic2Absolute(1, $month, $year) + 1;
165             }
166 1         11 return ($day, $month, $year);
167              
168             }
169              
170             1;
171             __END__