File Coverage

blib/lib/DateTime/Format/Roman.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package DateTime::Format::Roman;
2              
3 4     4   732321 use strict;
  4         12  
  4         166  
4              
5 4     4   21 use vars qw($VERSION);
  4         10  
  4         253  
6              
7             $VERSION = 0.03;
8              
9 4     4   1780 use DateTime 0.22;
  4         206070  
  4         99  
10              
11 4     4   5551 use Roman;
  0            
  0            
12             use Params::Validate qw/validate SCALAR ARRAYREF/;
13              
14             sub new {
15             my $class = shift;
16             my %p = validate( @_,
17             { pattern => {type => SCALAR | ARRAYREF,
18             default => '%Od %2f %B %Oy' },
19             } );
20              
21             $p{pattern} = [$p{pattern}] unless ref $p{pattern};
22              
23             my $self = bless \%p, $class;
24             return $self;
25             }
26              
27             my @fixed_days_names = (
28             { Kal => 'Kal', Non => 'Non', Id => 'Id' },
29             { Kal => 'K', Non => 'N', Id => 'Id' },
30             { Kal => 'Kalends', Non => 'Nones', Id => 'Ides' },
31             );
32              
33             my %dt_elem;
34             my %formats;
35             %formats =
36             ( 'b' => sub { (shift->language->month_abbreviations)->[$dt_elem{month}-1] },
37             'B' => sub { (shift->language->month_names)->[$dt_elem{month}-1] },
38             'd' => sub { $dt_elem{day} },
39             'D' => sub { ($dt_elem{day} ne 1 && $dt_elem{day}.' ') . $formats{f}->(@_) },
40             'f' => sub { $fixed_days_names[$_[1]||0]{$dt_elem{fixed_day}} },
41             'm' => sub { $dt_elem{month} },
42             'y' => sub { $dt_elem{year} },
43             );
44              
45             my $default_formatter;
46              
47             sub format_datetime {
48             my ($self, $dt) = @_;
49              
50             unless (ref $self) {
51             # Called as a class method
52             $default_formatter ||= $self->new();
53             $self = $default_formatter;
54             }
55              
56             %dt_elem = DateTime::Format::Roman->date_elements($dt);
57              
58             my @return;
59             for (@{$self->{pattern}}) {
60             my $pat = $_;
61             $pat =~ s/%([Oo]?)(\d*)([a-zA-Z])/
62             $formats{$3} ?
63             _romanize($formats{$3}->($dt, $2),$1)
64             : "$1$2$3" /ge;
65             return $pat unless wantarray;
66             push @return, $pat;
67             }
68             return @return;
69             }
70              
71             sub _romanize {
72             my ($str, $extra) = @_;
73             if ($extra eq 'O') {
74             $str =~ s/(\d+)(\w?)/Roman($1) . ($2?" $2":'')/ge;
75             } elsif ($extra eq 'o') {
76             $str =~ s/(\d+)(\w?)/roman($1) . ($2?" $2":'')/ge;
77             }
78             return $str;
79             }
80              
81             sub date_elements {
82             my ($self, $dt) = @_;
83              
84             my ($d, $m, $y) = ($dt->day, $dt->month, $dt->year);
85             my $nones = _nones($m);
86             my $ides = $nones + 8;
87              
88             my %retval;
89              
90             if ($d == 1) {
91             @retval{'day', 'fixed_day'} = (1, 'Kal');
92             } elsif ($d <= $nones) {
93             @retval{'day', 'fixed_day'} = ($nones + 1 - $d, 'Non');
94             } elsif ($d <= $ides) {
95             @retval{'day', 'fixed_day'} = ($ides + 1 - $d, 'Id');
96             } else {
97             my $days_in_month = (ref $dt)->last_day_of_month(
98             year => $y, month => $m )->day;
99             my $day = $days_in_month + 2 - $d;
100              
101             # In leap years, 6 Kal March is doubled (24&25 Feb)
102             if ($dt->is_leap_year && $m == 2) {
103             if ($day > 7) {
104             $day --;
105             } elsif ($day == 7) {
106             $day = '6bis';
107             }
108             }
109             @retval{'day', 'fixed_day'} = ($day, 'Kal');
110             $m++;
111             if ($m > 12) {
112             $m -= 12;
113             $y++;
114             }
115             }
116              
117             @retval{'month', 'year'} = ($m, $y);
118             return %retval;
119             }
120              
121             sub _nones {
122             my $m = shift;
123             return 7 if $m == 3 or $m == 5 or $m == 7 or $m == 10;
124             return 5;
125             }
126              
127             1;
128             __END__