File Coverage

blib/lib/Date/Utils/Persian.pm
Criterion Covered Total %
statement 57 61 93.4
branch 8 14 57.1
condition n/a
subroutine 12 12 100.0
pod 6 6 100.0
total 83 93 89.2


line stmt bran cond sub pod time code
1             package Date::Utils::Persian;
2              
3             $Date::Utils::Persian::VERSION = '0.02';
4              
5             =head1 NAME
6              
7             Date::Utils::Persian - Persian date specific routines as Moo Role.
8              
9             =head1 VERSION
10              
11             Version 0.02
12              
13             =cut
14              
15 2     2   22315 use 5.006;
  2         5  
  2         70  
16 2     2   13463 use Data::Dumper;
  2         17033  
  2         159  
17 2     2   1155 use POSIX qw/floor ceil/;
  2         12261  
  2         18  
18 2     2   3324 use Date::Calc qw/Delta_Days/;
  2         12726  
  2         189  
19              
20 2     2   544 use Moo::Role;
  2         137839  
  2         12  
21 2     2   1052 use namespace::clean;
  2         9311  
  2         10  
22              
23             our $PERSIAN_MONTHS = [
24             '',
25             'Farvardin', 'Ordibehesht', 'Khordad', 'Tir', 'Mordad', 'Shahrivar',
26             'Mehr' , 'Aban' , 'Azar' , 'Dey', 'Bahman', 'Esfand'
27             ];
28              
29             our $PERSIAN_DAYS = [
30             ' Yekshanbeh ',
31             ' Doshanbeh ',
32             ' Seshhanbeh ',
33             ' Chaharshanbeh ',
34             ' Panjshanbeh ',
35             ' Jomeh ',
36             ' Shanbeh '
37             ];
38              
39             has persian_epoch => (is => 'ro', default => sub { 1948320.5 });
40             has persian_days => (is => 'ro', default => sub { $PERSIAN_DAYS });
41             has persian_months => (is => 'ro', default => sub { $PERSIAN_MONTHS });
42              
43             with 'Date::Utils';
44              
45             =head1 DESCRIPTION
46              
47             Persian date specific routines as Moo ROle.
48              
49             =head1 METHODS
50              
51             =head2 persian_to_gregorian($year, $month, $day)
52              
53             Returns Gregorian date as list (year, month, day) equivalent of the given Persian
54             date.
55              
56             =cut
57              
58             sub persian_to_gregorian {
59 3     3 1 4 my ($self, $year, $month, $day) = @_;
60              
61 3         8 $self->validate_date($year, $month, $day);
62 3         46 ($year, $month, $day) = $self->julian_to_gregorian($self->persian_to_julian($year, $month, $day));
63              
64 3         119 return ($year, $month, $day);
65             }
66              
67             =head2 gregorian_to_persian($year, $month, $day)
68              
69             Returns Persian date as list (year, month, day) equivalent of the given Gregorian
70             date.
71              
72             =cut
73              
74             sub gregorian_to_persian {
75 1     1 1 16 my ($self, $year, $month, $day) = @_;
76              
77 1         4 $self->validate_date($year, $month, $day);
78 1         17 my $julian = $self->gregorian_to_julian($year, $month, $day) + (floor(0 + 60 * (0 + 60 * 0) + 0.5) / 86400.0);
79 1         15 ($year, $month, $day) = $self->julian_to_persian($julian);
80              
81 1         9 return ($year, $month, $day);
82             }
83              
84             =head2 persian_to_julian($year, $month. $day)
85              
86             Returns Julian date of the given Persian date.
87              
88             =cut
89              
90             sub persian_to_julian {
91 10     10 1 1653 my ($self, $year, $month, $day) = @_;
92              
93 10 50       17 my $epbase = $year - (($year >= 0) ? 474 : 473);
94 10         10 my $epyear = 474 + ($epbase % 2820);
95              
96 10 100       69 return $day + (($month <= 7)?(($month - 1) * 31):((($month - 1) * 30) + 6)) +
97             floor((($epyear * 682) - 110) / 2816) +
98             ($epyear - 1) * 365 +
99             floor($epbase / 2820) * 1029983 +
100             ($self->persian_epoch - 1);
101             }
102              
103             =head2 julian_to_persian($julian_date)
104              
105             Returns Persian date as list (year, month, day) equivalent of the given Julian
106             date.
107              
108             =cut
109              
110             sub julian_to_persian {
111 2     2 1 3 my ($self, $julian) = @_;
112              
113 2         4 $julian = floor($julian) + 0.5;
114 2         5 my $depoch = $julian - $self->persian_to_julian(475, 1, 1);
115 2         5 my $cycle = floor($depoch / 1029983);
116 2         3 my $cyear = $depoch % 1029983;
117              
118 2         1 my $ycycle;
119 2 50       6 if ($cyear == 1029982) {
120 0         0 $ycycle = 2820;
121             }
122             else {
123 2         5 my $aux1 = floor($cyear / 366);
124 2         3 my $aux2 = $cyear % 366;
125 2         4 $ycycle = floor(((2134 * $aux1) + (2816 * $aux2) + 2815) / 1028522) + $aux1 + 1;
126             }
127              
128 2         3 my $year = $ycycle + (2820 * $cycle) + 474;
129 2 50       6 if ($year <= 0) {
130 0         0 $year--;
131             }
132              
133 2         4 my $yday = ($julian - $self->persian_to_julian($year, 1, 1)) + 1;
134 2 50       8 my $month = ($yday <= 186) ? ceil($yday / 31) : ceil(($yday - 6) / 30);
135 2         5 my $day = ($julian - $self->persian_to_julian($year, $month, 1)) + 1;
136              
137 2         10 return ($year, $month, $day);
138             }
139              
140             =head2 is_persian_leap_year($year)
141              
142             Returns 0 or 1 if the given Persian year C<$year> is a leap year or not.
143              
144             =cut
145              
146             sub is_persian_leap_year {
147 1     1 1 2 my ($self, $year) = @_;
148              
149 1 50       8 return (((((($year - (($year > 0) ? 474 : 473)) % 2820) + 474) + 38) * 682) % 2816) < 682;
150             }
151              
152             =head2 days_in_persian_month_year($month, $year)
153              
154             Returns total number of days in the given Persian month year.
155              
156             =cut
157              
158             sub days_in_persian_month_year {
159 1     1 1 2 my ($self, $month, $year) = @_;
160              
161 1         4 $self->validate_year($year);
162 1         8 $self->validate_month($month);
163              
164 1         6 my @start = $self->persian_to_gregorian($year, $month, 1);
165 1 50       3 if ($month == 12) {
166 0         0 $year += 1;
167 0         0 $month = 1;
168             }
169             else {
170 1         2 $month += 1;
171             }
172              
173 1         2 my @end = $self->persian_to_gregorian($year, $month, 1);
174              
175 1         14 return Delta_Days(@start, @end);
176             }
177              
178             =head1 AUTHOR
179              
180             Mohammad S Anwar, C<< >>
181              
182             =head1 REPOSITORY
183              
184             L
185              
186             =head1 ACKNOWLEDGEMENTS
187              
188             Entire logic is based on the L written by John Walker.
189              
190             =head1 BUGS
191              
192             Please report any bugs / feature requests to C
193             , or through the web interface at L.
194             I will be notified, and then you'll automatically be notified of progress on your
195             bug as I make changes.
196              
197             =head1 SUPPORT
198              
199             You can find documentation for this module with the perldoc command.
200              
201             perldoc Date::Utils::Persian
202              
203             You can also look for information at:
204              
205             =over 4
206              
207             =item * RT: CPAN's request tracker
208              
209             L
210              
211             =item * AnnoCPAN: Annotated CPAN documentation
212              
213             L
214              
215             =item * CPAN Ratings
216              
217             L
218              
219             =item * Search CPAN
220              
221             L
222              
223             =back
224              
225             =head1 LICENSE AND COPYRIGHT
226              
227             Copyright (C) 2015 Mohammad S Anwar.
228              
229             This program is free software; you can redistribute it and / or modify it under
230             the terms of the the Artistic License (2.0). You may obtain a copy of the full
231             license at:
232              
233             L
234              
235             Any use, modification, and distribution of the Standard or Modified Versions is
236             governed by this Artistic License.By using, modifying or distributing the Package,
237             you accept this license. Do not use, modify, or distribute the Package, if you do
238             not accept this license.
239              
240             If your Modified Version has been derived from a Modified Version made by someone
241             other than you,you are nevertheless required to ensure that your Modified Version
242             complies with the requirements of this license.
243              
244             This license does not grant you the right to use any trademark, service mark,
245             tradename, or logo of the Copyright Holder.
246              
247             This license includes the non-exclusive, worldwide, free-of-charge patent license
248             to make, have made, use, offer to sell, sell, import and otherwise transfer the
249             Package with respect to any patent claims licensable by the Copyright Holder that
250             are necessarily infringed by the Package. If you institute patent litigation
251             (including a cross-claim or counterclaim) against any party alleging that the
252             Package constitutes direct or contributory patent infringement,then this Artistic
253             License to you shall terminate on the date that such litigation is filed.
254              
255             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND
256             CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
257             WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
258             NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS
259             REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT,
260             INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
261             OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
262              
263             =cut
264              
265             1; # End of Date::Utils::Persian