File Coverage

blib/lib/Date/Saka/Simple.pm
Criterion Covered Total %
statement 141 160 88.1
branch 36 56 64.2
condition 4 6 66.6
subroutine 27 27 100.0
pod 11 15 73.3
total 219 264 82.9


line stmt bran cond sub pod time code
1             package Date::Saka::Simple;
2              
3             $Date::Saka::Simple::VERSION = '0.24';
4             $Date::Saka::Simple::AUTHORITY = 'cpan:MANWAR';
5              
6             =head1 NAME
7              
8             Date::Saka::Simple - Represents Saka date.
9              
10             =head1 VERSION
11              
12             Version 0.24
13              
14             =cut
15              
16 2     2   135528 use 5.006;
  2         15  
17 2     2   1223 use Data::Dumper;
  2         13514  
  2         120  
18 2     2   870 use Time::localtime;
  2         9483  
  2         113  
19 2     2   15 use List::Util qw/min/;
  2         4  
  2         190  
20 2     2   1036 use POSIX qw/floor/;
  2         12333  
  2         12  
21 2     2   3684 use Date::Calc qw(Add_Delta_Days Delta_Days);
  2         15349  
  2         162  
22 2     2   933 use Date::Exception::InvalidDayCount;
  2         128464  
  2         78  
23 2     2   947 use Date::Exception::InvalidMonthCount;
  2         5829  
  2         67  
24 2     2   944 use Date::Exception::InvalidYearCount;
  2         5292  
  2         79  
25              
26 2     2   17 use Moo;
  2         3  
  2         9  
27 2     2   717 use namespace::autoclean;
  2         3  
  2         9  
28              
29 2     2   129 use overload q{""} => 'as_string', fallback => 1;
  2         4  
  2         26  
30              
31             =head1 DESCRIPTION
32              
33             Represents the Saka date.
34              
35             =cut
36              
37             my $SAKA_START = 80;
38             my $SAKA_OFFSET = 78;
39              
40             my $SAKA_MONTHS = [
41             undef,
42             'Chaitra', 'Vaisakha', 'Jyaistha', 'Asadha', 'Sravana', 'Bhadra',
43             'Asvina', 'Kartika', 'Agrahayana', 'Pausa', 'Magha', 'Phalguna'
44             ];
45              
46             my $SAKA_DAYS = [
47             'Ravivara', 'Somvara', 'Mangalavara', 'Budhavara',
48             'Brahaspativara', 'Sukravara', 'Sanivara'
49             ];
50              
51             has days => (is => 'ro', default => sub { $SAKA_DAYS });
52             has months => (is => 'ro', default => sub { $SAKA_MONTHS });
53             has saka_start => (is => 'ro', default => sub { $SAKA_START });
54             has saka_offset => (is => 'ro', default => sub { $SAKA_OFFSET });
55              
56             has year => (is => 'rw', predicate => 1);
57             has month => (is => 'rw', predicate => 1);
58             has day => (is => 'rw', predicate => 1);
59              
60             with 'Date::Utils';
61              
62             sub BUILD {
63 11     11 0 58 my ($self) = @_;
64              
65 11 100       55 $self->validate_year($self->year) if $self->has_year;
66 11 100       187 $self->validate_month($self->month) if $self->has_month;
67 11 100       176 $self->validate_day($self->day) if $self->has_day;
68              
69 11 100 66     206 unless ($self->has_year && $self->has_month && $self->has_day) {
      66        
70 2         8 my $today = localtime;
71 2         326 my $year = $today->year + 1900;
72 2         40 my $month = $today->mon + 1;
73 2         42 my $day = $today->mday;
74 2         15 my $date = $self->from_gregorian($year, $month, $day);
75 2         8 $self->year($date->year);
76 2         13 $self->month($date->month);
77 2         19 $self->day($date->day);
78             }
79             }
80              
81             =head1 SYNOPSIS
82              
83             use strict; use warnings;
84             use Date::Saka::Simple;
85              
86             # prints today's Saka date
87             print Date::Saka::Simple->new, "\n";
88              
89             my $date = Date::Saka::Simple->new({ year => 1937, month => 1, day => 1 });
90              
91             # prints the given Saka date
92             print $date->as_string, "\n";
93              
94             # prints the equivalent Julian date
95             print $date->to_julian, "\n";
96              
97             # prints the equivalent Gregorian date
98             print sprintf("%04d-%02d-%02d", $date->to_gregorian), "\n";
99              
100             # prints day of the week index (0 for Ravivara, 1 for Somvara and so on).
101             print $date->day_of_week, "\n";
102              
103             # add days to the given Saka date and print
104             print $date->add_days(2)->as_string, "\n";
105              
106             # minus days to the given Saka date and print
107             print $date->minus_days(2)->as_string, "\n";
108              
109             # add months to the given Saka date and print
110             print $date->add_months(2)->as_string, "\n";
111              
112             # minus months to the given Saka date and print
113             print $date->minus_months(2)->as_string, "\n";
114              
115             # add years to the given Saka date and print
116             print $date->add_years(2)->as_string, "\n";
117              
118             # minus years to the given Saka date and print
119             print $date->minus_years(2)->as_string, "\n";
120              
121             =head1 METHODS
122              
123             =head2 to_julian()
124              
125             Returns julian date equivalent of the Saka date.
126              
127             =cut
128              
129             sub to_julian {
130 7     7 1 450 my ($self) = @_;
131              
132 7         21 my $gregorian_year = $self->year + 78;
133 7 100       18 my $gregorian_day = ($self->is_gregorian_leap_year($gregorian_year)) ? (21) : (22);
134 7         57 my $start = $self->gregorian_to_julian($gregorian_year, 3, $gregorian_day);
135              
136 7         110 my ($julian);
137 7 100       19 if ($self->month == 1) {
138 5         13 $julian = $start + ($self->day - 1);
139             }
140             else {
141 2 50       5 my $chaitra = ($self->is_gregorian_leap_year($gregorian_year)) ? (31) : (30);
142 2         12 $julian = $start + $chaitra;
143 2         5 my $_month = $self->month - 2;
144 2         7 $_month = min($_month, 5);
145 2         5 $julian += $_month * 31;
146              
147 2 50       8 if ($self->month >= 8) {
148 0         0 $_month = $self->month - 7;
149 0         0 $julian += $_month * 30;
150             }
151              
152 2         6 $julian += $self->day - 1;
153             }
154              
155 7         21 return $julian;
156             }
157              
158             =head2 from_julian($julian_date)
159              
160             Returns Saka date as an object of type L equivalent of the
161             Julian date C<$julian_date>.
162              
163             =cut
164              
165             sub from_julian {
166 6     6 1 1639 my ($self, $julian_date) = @_;
167              
168 6         16 $julian_date = floor($julian_date) + 0.5;
169 6         13 my $year = ($self->julian_to_gregorian($julian_date))[0];
170 6         302 my $yday = $julian_date - $self->gregorian_to_julian($year, 1, 1);
171 6         42 my $chaitra = $self->days_in_chaitra($year);
172 6         41 $year = $year - $self->saka_offset;
173              
174 6 50       20 if ($yday < $self->saka_start) {
175 0         0 $year--;
176 0         0 $yday += $chaitra + (31 * 5) + (30 * 3) + 10 + $self->saka_start;
177             }
178 6         10 $yday -= $self->saka_start;
179              
180 6         11 my ($day, $month);
181 6 100       13 if ($yday < $chaitra) {
182 4         7 $month = 1;
183 4         5 $day = $yday + 1;
184             }
185             else {
186 2         3 my $mday = $yday - $chaitra;
187 2 50       6 if ($mday < (31 * 5)) {
188 2         7 $month = floor($mday / 31) + 2;
189 2         4 $day = ($mday % 31) + 1;
190             }
191             else {
192 0         0 $mday -= 31 * 5;
193 0         0 $month = floor($mday / 30) + 7;
194 0         0 $day = ($mday % 30) + 1;
195             }
196             }
197              
198 6         141 return Date::Saka::Simple->new({ year => $year, month => $month, day => $day });
199             }
200              
201             =head2 to_gregorian()
202              
203             Returns gregorian date as list (yyyy,mm,dd) equivalent of the Saka date.
204              
205             =cut
206              
207             sub to_gregorian {
208 5     5 1 11 my ($self) = @_;
209              
210 5         11 return $self->julian_to_gregorian($self->to_julian);
211             }
212              
213             =head2 from_gregorian($year, $month, $day)
214              
215             Returns Saka date as an object of type L equivalent of the
216             given Gregorian date C<$year>, C<$month> and C<$day>.
217              
218             =cut
219              
220             sub from_gregorian {
221 5     5 1 552 my ($self, $year, $month, $day) = @_;
222              
223 5         15 return $self->from_julian($self->gregorian_to_julian($year, $month, $day));
224             }
225              
226             =head2 day_of_week()
227              
228             Returns day of the week, starting 0 for Ravivara, 1 for Somvara and so on.
229              
230             +---------+-----------+-----------------------------------------------------+
231             | Weekday | Gregorian | Saka |
232             +---------+-----------+-----------------------------------------------------+
233             | 0 | Sunday | Ravivara |
234             | 1 | Monday | Somvara |
235             | 2 | Tuesday | Mangalavara |
236             | 3 | Wednesday | Budhavara |
237             | 4 | Thursday | Brahaspativara |
238             | 5 | Friday | Sukravara |
239             | 6 | Saturday | Sanivara |
240             +---------+-----------+-----------------------------------------------------+
241              
242             =cut
243              
244             sub day_of_week {
245 1     1 1 4 my ($self) = @_;
246              
247 1         4 return $self->jwday($self->to_julian);
248             }
249              
250             =head2 add_days()
251              
252             Add given number of days to the Saka date.
253              
254             =cut
255              
256             sub add_days {
257 2     2 1 569 my ($self, $no_of_days) = @_;
258              
259 2         13 my @caller = caller(0);
260 2 50       7 @caller = caller(2) if $caller[3] eq '(eval)';
261              
262 2 50       12 Date::Exception::InvalidDayCount->throw({
263             method => __PACKAGE__."::add_days",
264             message => 'ERROR: Invalid day count.',
265             filename => $caller[1],
266             line_number => $caller[2] })
267             unless ($no_of_days =~ /^\-?\d+$/);
268              
269 2         6 my ($year, $month, $day) = $self->to_gregorian();
270 2         106 ($year, $month, $day) = Add_Delta_Days($year, $month, $day, $no_of_days);
271 2         46 my $date = Date::Saka::Simple->new->from_gregorian($year, $month, $day);
272              
273 2         10 $self->year($date->year);
274 2         7 $self->month($date->month);
275 2         7 $self->day($date->day);
276              
277 2         6 return $self;
278             }
279              
280             =head2 minus_days()
281              
282             Minus given number of days from the Saka date.
283              
284             =cut
285              
286             sub minus_days {
287 1     1 1 596 my ($self, $no_of_days) = @_;
288              
289 1         8 my @caller = caller(0);
290 1 50       8 @caller = caller(2) if $caller[3] eq '(eval)';
291              
292 1 50       7 Date::Exception::InvalidDayCount->throw({
293             method => __PACKAGE__."::minus_days",
294             message => 'ERROR: Invalid day count.',
295             filename => $caller[1],
296             line_number => $caller[2] })
297             unless ($no_of_days =~ /^\d+$/);
298              
299 1         4 $self->add_days(-1 * $no_of_days);
300              
301 1         4 return $self;
302             }
303              
304             =head2 add_months()
305              
306             Add given number of months to the Saka date.
307              
308             =cut
309              
310             sub add_months {
311 1     1 1 589 my ($self, $no_of_months) = @_;
312              
313 1         9 my @caller = caller(0);
314 1 50       5 @caller = caller(2) if $caller[3] eq '(eval)';
315              
316 1 50       7 Date::Exception::InvalidMonthCount->throw({
317             method => __PACKAGE__."::add_months",
318             message => 'ERROR: Invalid month count.',
319             filename => $caller[1],
320             line_number => $caller[2] })
321             unless ($no_of_months =~ /^\d+$/);
322              
323 1 50       7 if (($self->month + $no_of_months) > 12) {
324 0         0 while (($self->month + $no_of_months) > 12) {
325 0         0 my $_month = 12 - $self->month;
326 0         0 $self->year($self->year + 1);
327 0         0 $self->month(1);
328 0         0 $no_of_months = $no_of_months - ($_month + 1);
329             }
330             }
331              
332 1         6 $self->month($self->month + $no_of_months);
333              
334 1         3 return $self;
335             }
336              
337             =head2 minus_months()
338              
339             Minus given number of months from the Saka date.
340              
341             =cut
342              
343             sub minus_months {
344 1     1 1 534 my ($self, $no_of_months) = @_;
345              
346 1         9 my @caller = caller(0);
347 1 50       5 @caller = caller(2) if $caller[3] eq '(eval)';
348              
349 1 50       9 Date::Exception::InvalidMonthCount->throw({
350             method => __PACKAGE__."::minus_months",
351             message => 'ERROR: Invalid month count.',
352             filename => $caller[1],
353             line_number => $caller[2] })
354             unless ($no_of_months =~ /^\d+$/);
355              
356 1 50       6 if (($self->month - $no_of_months) < 1) {
357 0         0 while (($self->{mm} - $no_of_months) < 1) {
358 0         0 my $_month = $no_of_months - $self->month;
359 0         0 $self->year($self->year - 1);
360 0         0 $no_of_months = $no_of_months - $self->month;
361 0         0 $self->month(12);
362             }
363             }
364              
365 1         5 $self->month($self->month - $no_of_months);
366              
367 1         5 return $self;
368             }
369              
370             =head2 add_years()
371              
372             Add given number of years to the Saka date.
373              
374             =cut
375              
376             sub add_years {
377 1     1 1 557 my ($self, $no_of_years) = @_;
378              
379 1         8 my @caller = caller(0);
380 1 50       5 @caller = caller(2) if $caller[3] eq '(eval)';
381              
382 1 50       7 Date::Exception::InvalidYearCount->throw({
383             method => __PACKAGE__."::add_years",
384             message => 'ERROR: Invalid year count.',
385             filename => $caller[1],
386             line_number => $caller[2] })
387             unless ($no_of_years =~ /^\d+$/);
388              
389 1         13 $self->year($self->year + $no_of_years);
390              
391 1         4 return $self;
392             }
393              
394             =head2 minus_years()
395              
396             Minus given number of years from the Saka date.
397              
398             =cut
399              
400             sub minus_years {
401 1     1 1 545 my ($self, $no_of_years) = @_;
402              
403 1         8 my @caller = caller(0);
404 1 50       5 @caller = caller(2) if $caller[3] eq '(eval)';
405              
406 1 50       7 Date::Exception::InvalidYearCount->throw({
407             method => __PACKAGE__."::minus_years",
408             message => 'ERROR: Invalid year count.',
409             filename => $caller[1],
410             line_number => $caller[2] })
411             unless ($no_of_years =~ /^\d+$/);
412              
413 1         5 $self->year($self->year - $no_of_years);
414              
415 1         32 return $self;
416             }
417              
418             sub days_in_chaitra {
419 6     6 0 20 my ($self, $year) = @_;
420              
421 6         14 $self->days_in_month_year(1, $year);
422             }
423              
424             sub days_in_month_year {
425 8     8 0 552 my ($self, $month, $year) = @_;
426              
427 8 100       19 if ($month == 1) {
428 7 50       16 return ($self->is_gregorian_leap_year($year)) ? (return 31) : (return 30);
429             }
430             else {
431 1         27 my @start = Date::Saka::Simple->new({ year => $year, month => $month, day => 1 })->to_gregorian;
432 1 50       76 if ($month == 12) {
433 0         0 $year += 1;
434 0         0 $month = 1;
435             }
436             else {
437 1         3 $month += 1;
438             }
439              
440 1         23 my @end = Date::Saka::Simple->new({ year => $year, month => $month, day => 1 })->to_gregorian;
441              
442 1         62 return Delta_Days(@start, @end);
443             }
444             }
445              
446             sub as_string {
447 7     7 0 332 my ($self) = @_;
448              
449 7         25 return sprintf("%02d, %s %04d", $self->day, $self->get_month_name, $self->year);
450             }
451              
452             =head1 AUTHOR
453              
454             Mohammad S Anwar, C<< >>
455              
456             =head1 REPOSITORY
457              
458             L
459              
460             =head1 SEE ALSO
461              
462             =over 4
463              
464             =item L
465              
466             =item L
467              
468             =item L
469              
470             =item L
471              
472             =item L
473              
474             =item L
475              
476             =back
477              
478             =head1 BUGS
479              
480             Please report any bugs / feature requests to C,
481             or through the web interface at L.
482             I will be notified, and then you'll automatically be notified of progress on your
483             bug as I make changes.
484              
485             =head1 SUPPORT
486              
487             You can find documentation for this module with the perldoc command.
488              
489             perldoc Date::Saka::Simple
490              
491             You can also look for information at:
492              
493             =over 4
494              
495             =item * RT: CPAN's request tracker
496              
497             L
498              
499             =item * AnnoCPAN: Annotated CPAN documentation
500              
501             L
502              
503             =item * CPAN Ratings
504              
505             L
506              
507             =item * Search CPAN
508              
509             L
510              
511             =back
512              
513             =head1 LICENSE AND COPYRIGHT
514              
515             Copyright (C) 2015 - 2016 Mohammad S Anwar.
516              
517             This program is free software; you can redistribute it and / or modify it under
518             the terms of the the Artistic License (2.0). You may obtain a copy of the full
519             license at:
520              
521             L
522              
523             Any use, modification, and distribution of the Standard or Modified Versions is
524             governed by this Artistic License.By using, modifying or distributing the Package,
525             you accept this license. Do not use, modify, or distribute the Package, if you do
526             not accept this license.
527              
528             If your Modified Version has been derived from a Modified Version made by someone
529             other than you,you are nevertheless required to ensure that your Modified Version
530             complies with the requirements of this license.
531              
532             This license does not grant you the right to use any trademark, service mark,
533             tradename, or logo of the Copyright Holder.
534              
535             This license includes the non-exclusive, worldwide, free-of-charge patent license
536             to make, have made, use, offer to sell, sell, import and otherwise transfer the
537             Package with respect to any patent claims licensable by the Copyright Holder that
538             are necessarily infringed by the Package. If you institute patent litigation
539             (including a cross-claim or counterclaim) against any party alleging that the
540             Package constitutes direct or contributory patent infringement,then this Artistic
541             License to you shall terminate on the date that such litigation is filed.
542              
543             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND
544             CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
545             WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
546             NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS
547             REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT,
548             INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE
549             OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
550              
551             =cut
552              
553             1; # End of Date::Saka::Simple