File Coverage

blib/lib/DateTime/Format/Japanese/Traditional.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             # $Id: /mirror/datetime/DateTime-Format-Japanese/trunk/lib/DateTime/Format/Japanese/Traditional.pm 69499 2008-08-24T16:17:57.045540Z lestrrat $
2              
3             package DateTime::Format::Japanese::Traditional;
4 2     2   82720 use strict;
  2         4  
  2         86  
5 2     2   12 use warnings;
  2         3  
  2         102  
6 2     2   2818 use utf8;
  2         22  
  2         11  
7 2     2   1218 use DateTime::Calendar::Japanese;
  0            
  0            
8             use DateTime::Calendar::Japanese::Era;
9             use DateTime::Format::Japanese::Common qw(:constants);
10             use Exporter;
11             use Params::Validate qw(validate validate_pos SCALAR BOOLEAN);
12             use constant FORMAT_NUMERIC_MONTH => 'FORMAT_NUMERIC_MONTH';
13             use constant FORMAT_WAREKI_MONTH => 'FORMAT_WAREKI_MONTH';
14             use vars qw(@ISA %EXPORT_TAGS);
15             BEGIN
16             {
17             @ISA = qw(Exporter);
18             %EXPORT_TAGS = (
19             constants => [ qw(
20             FORMAT_KANJI_WITH_UNIT FORMAT_KANJI FORMAT_ZENKAKU
21             FORMAT_ROMAN FORMAT_NUMERIC_MONTH FORMAT_WAREKI_MONTH) ]
22             );
23             Exporter::export_ok_tags('constants');
24             }
25             # Got to call these after we define constants
26              
27              
28             use vars qw(
29             @WAREKI_MONTHS @ZODIAC_HOURS %WAREKI2MONTH %ZODIAC2HOUR
30             $HOUR_NO_QUARTER_MARKER
31             $HOUR_WITH_QUARTER_MARKER
32             $RE_WAREKI_MONTH
33             $RE_HOUR_NO_QUARTER_MARKER
34             $RE_HOUR_WITH_QUARTER_MARKER
35             $RE_ZODIAC_HOUR
36             );
37              
38             {
39             @WAREKI_MONTHS = qw(睦月 如月 弥生 卯月 皐月 水無月 文月 葉月 長月 神無月 霜月 師走);
40             %WAREKI2MONTH = map { ($WAREKI_MONTHS[$_] => $_ + 1) } 0 .. $#WAREKI_MONTHS;
41              
42             @ZODIAC_HOURS = qw(卯 辰 巳 午 未 申 酉 戌 亥 子 丑 寅);
43             %ZODIAC2HOUR = map { ($ZODIAC_HOURS[$_] => $_ + 1) } 0 .. $#ZODIAC_HOURS;
44              
45             $HOUR_NO_QUARTER_MARKER = 'の刻';
46             $HOUR_WITH_QUARTER_MARKER = 'つ刻';
47              
48             $RE_WAREKI_MONTH = DateTime::Format::Japanese::Common::_make_re(join( "|",
49             map { DateTime::Format::Japanese::Common::_make_utf8_re_str($_) }
50             @WAREKI_MONTHS ));
51             $RE_HOUR_NO_QUARTER_MARKER =
52             DateTime::Format::Japanese::Common::_make_utf8_re(
53             $HOUR_NO_QUARTER_MARKER);
54             $RE_HOUR_WITH_QUARTER_MARKER =
55             DateTime::Format::Japanese::Common::_make_utf8_re(
56             $HOUR_WITH_QUARTER_MARKER);
57             $RE_ZODIAC_HOUR = DateTime::Format::Japanese::Common::_make_re( join( '|', map {
58             DateTime::Format::Japanese::Common::_make_utf8_re_str($_) } @ZODIAC_HOURS) );
59             }
60              
61             my %NewValidate = (
62             output_encoding => { default => 'utf8' },
63             input_encoding => { default => 'utf8' },
64             number_format => {
65             type => SCALAR,
66             default => FORMAT_KANJI
67             },
68             month_format => {
69             type => SCALAR,
70             default => FORMAT_NUMERIC_MONTH
71             },
72             with_traditional_marker => {
73             type => BOOLEAN,
74             default => 1
75             }
76             );
77              
78             sub new
79             {
80             my $class = shift;
81             my %hash = validate(@_, \%NewValidate);
82             my $self = bless \%hash, $class;
83             }
84              
85             sub input_encoding
86             {
87             my $self = shift;
88             my $ret = $self->{input_encoding};
89             if (@_) {
90             $self->{input_encoding} = shift;
91             }
92             return $ret;
93             }
94              
95             sub output_encoding
96             {
97             my $self = shift;
98             my $ret = $self->{output_encoding};
99             if (@_) {
100             $self->{output_encoding} = shift;
101             }
102             return $ret;
103             }
104              
105             sub number_format
106             {
107             my $self = shift;
108             my $current = $self->{number_format};
109             if (@_) {
110             my($val) = validate_pos(@_, {
111             type => SCALAR,
112             callbacks => {
113             'is valid number_format' => \&DateTime::Format::Japanese::Common::_valid_number_format
114             }
115             });
116             $self->{number_format} = $val;
117             }
118             return $current;
119             }
120              
121             sub month_format
122             {
123             my $self = shift;
124             my $current = $self->{month_format};
125             if (@_) {
126             my($val) = validate_pos(@_, {
127             type => SCALAR,
128             callbacks => {
129             'is valid month_format' => sub {
130             $_[0] eq FORMAT_NUMERIC_MONTH ||
131             $_[0] eq FORMAT_WAREKI_MONTH
132             }
133             }
134             });
135             $self->{month_format} = $val;
136             }
137             return $current;
138             }
139              
140             sub with_traditional_marker
141             {
142             my $self = shift;
143             my $current = $self->{with_traditional_marker};
144             if (@_) {
145             my($val) = validate_pos(@_, { type => BOOLEAN });
146             $self->{with_traditional_marker} = $val;
147             }
148             return $current;
149             }
150              
151             my @FmtBasicValidate = (
152             { isa => 'DateTime::Calendar::Japanese' },
153             );
154              
155             sub format_datetime
156             {
157             my $self = shift;
158             my ($dt) = validate_pos(@_, @FmtBasicValidate);
159              
160             return $self->format_ymd($dt) .
161             $self->format_time($dt);
162             }
163              
164             sub format_year
165             {
166             my $self = shift;
167             my ($dt) = validate_pos(@_, @FmtBasicValidate);
168              
169             my $era_name = $dt->era->name;
170              
171             my $rv = '';
172             if ($self->with_traditional_marker) {
173             $rv .= $DateTime::Format::Japanese::Common::TRADITIONAL_MARKER;
174             }
175             $rv .= $era_name .
176             DateTime::Format::Japanese::Common::_format_number(
177             $dt->era_year, $self->number_format) .
178             $DateTime::Format::Japanese::Common::YEAR_MARKER;
179             return Encode::encode($self->{output_encoding}, $rv);
180             }
181              
182             sub format_month
183             {
184             my $self = shift;
185             my ($dt) = validate_pos(@_, @FmtBasicValidate);
186              
187             my $ret;
188             if ($self->month_format eq FORMAT_WAREKI_MONTH) {
189             $ret = $WAREKI_MONTHS[ $dt->month - 1 ];
190             } else {
191             $ret =
192             DateTime::Format::Japanese::Common::_format_common_with_marker(
193             $DateTime::Format::Japanese::Common::MONTH_MARKER,
194             $dt->month,
195             $self->number_format);
196             }
197             return Encode::encode($self->{output_encoding}, $ret);
198             }
199              
200             sub format_day
201             {
202             my $self = shift;
203             my ($dt) = validate_pos(@_, @FmtBasicValidate);
204              
205             return Encode::encode($self->{output_encoding},
206             DateTime::Format::Japanese::Common::_format_common_with_marker(
207             $DateTime::Format::Japanese::Common::DAY_MARKER,
208             $dt->day,
209             $self->number_format));
210             }
211              
212             sub format_ymd
213             {
214             my $self = shift;
215             my ($dt) = validate_pos(@_, @FmtBasicValidate);
216              
217             return $self->format_year($dt) .
218             $self->format_month($dt) .
219             $self->format_day($dt);
220              
221             }
222              
223             sub format_time
224             {
225             my $self = shift;
226             my ($dt) = validate_pos(@_, @FmtBasicValidate);
227              
228             my $ret;
229             if ($dt->hour_quarter > 1) {
230             $ret = $ZODIAC_HOURS[ $dt->hour - 1 ] .
231             DateTime::Format::Japanese::Common::_format_number(
232             $dt->hour_quarter, $self->number_format) .
233             $HOUR_WITH_QUARTER_MARKER;
234             } else {
235             $ret = $ZODIAC_HOURS[ $dt->hour - 1 ] .
236             $HOUR_NO_QUARTER_MARKER;
237             }
238              
239             return Encode::encode($self->{output_encoding}, $ret);
240             }
241              
242             sub _fix_era_name
243             {
244             my %args = @_;
245             my $era =
246             DateTime::Calendar::Japanese::Era->lookup_by_name(name => $args{parsed}->{era_name});
247              
248             if (!$era) {
249             return 0;
250             }
251              
252             $args{parsed}->{era_name} = $era->id;
253             }
254              
255             sub _fix_wareki_month
256             {
257             my %args = @_;
258             my $w_m = delete $args{parsed}->{wareki_month};
259             if (defined($w_m)) {
260             return $args{parsed}->{month} = $WAREKI2MONTH{ $w_m };
261             }
262             1;
263             }
264            
265              
266             sub _fix_zodiac_hour
267             {
268             my %args = @_;
269              
270             if (exists $args{parsed}->{zodiac_hour} ) {
271             my $zh = delete $args{parsed}->{zodiac_hour};
272             if (defined($zh)) {
273             return $args{parsed}->{hour} = $ZODIAC2HOUR{ $zh };
274             }
275             }
276             1;
277             }
278              
279             sub _fix_hour_quarter
280             {
281             my %args = @_;
282             if (exists $args{parsed}->{hour_quarter} && $args{parsed}->{hour_quarter} !~ /^[0-9]$/) {
283             my $h_q = delete $args{parsed}->{hour_quarter} ;
284             return $args{parsed}->{hour_quarter} =
285             $DateTime::Format::Japanese::Common::JP2ASCII{ $h_q };
286             }
287              
288             1;
289             }
290              
291             my $parse_standard = {
292             regex => qr<
293             ^
294             $DateTime::Format::Japanese::Common::RE_TRADITIONAL_MARKER?
295             ($DateTime::Format::Japanese::Common::RE_ERA_NAME)
296             ($DateTime::Format::Japanese::Common::RE_ERA_YEAR)
297             $DateTime::Format::Japanese::Common::RE_YEAR_MARKER
298             (?:
299             (?:
300             ($DateTime::Format::Japanese::Common::RE_TWO_DIGITS)
301             $DateTime::Format::Japanese::Common::RE_MONTH_MARKER
302             )
303             |
304             ($RE_WAREKI_MONTH)
305             )
306             ($DateTime::Format::Japanese::Common::RE_TWO_DIGITS)
307             $DateTime::Format::Japanese::Common::RE_DAY_MARKER
308             (?:($RE_ZODIAC_HOUR)
309             $RE_HOUR_NO_QUARTER_MARKER)?
310             $
311             >x,
312             constructor => [ 'DateTime::Calendar::Japanese', 'new' ],
313             params => [ qw(era_name era_year month wareki_month day zodiac_hour) ],
314             preprocess => [
315             \&DateTime::Format::Japanese::Common::_normalize_utf8, ],
316             postprocess => [
317             \&_fix_era_name,
318             \&DateTime::Format::Japanese::Common::_fix_era_year,
319             \&DateTime::Format::Japanese::Common::_normalize_numbers,
320             \&_fix_wareki_month,
321             \&_fix_zodiac_hour,
322             ]
323             };
324              
325             my $parse_standard_with_quarter = {
326             regex => qr<
327             ^
328             $DateTime::Format::Japanese::Common::RE_TRADITIONAL_MARKER?
329             ($DateTime::Format::Japanese::Common::RE_ERA_NAME)
330             ($DateTime::Format::Japanese::Common::RE_ERA_YEAR)
331             $DateTime::Format::Japanese::Common::RE_YEAR_MARKER
332             (?:
333             (?:
334             ($DateTime::Format::Japanese::Common::RE_TWO_DIGITS)
335             $DateTime::Format::Japanese::Common::RE_MONTH_MARKER
336             )
337             |
338             ($RE_WAREKI_MONTH)
339             )
340             ($DateTime::Format::Japanese::Common::RE_TWO_DIGITS)
341             $DateTime::Format::Japanese::Common::RE_DAY_MARKER
342             (?:
343             ($RE_ZODIAC_HOUR)
344             ($DateTime::Format::Japanese::Common::RE_JP_OR_ASCII_NUM)
345             $RE_HOUR_WITH_QUARTER_MARKER
346             )?
347             $
348             >x,
349             constructor => [ 'DateTime::Calendar::Japanese', 'new' ],
350             params => [ qw(era_name era_year month wareki_month day zodiac_hour hour_quarter) ],
351             preprocess => [
352             \&DateTime::Format::Japanese::Common::_normalize_utf8, ],
353             postprocess => [
354             \&_fix_era_name,
355             \&DateTime::Format::Japanese::Common::_fix_era_year,
356             \&DateTime::Format::Japanese::Common::_normalize_numbers,
357             \&_fix_wareki_month,
358             \&_fix_zodiac_hour,
359             \&_fix_hour_quarter,
360             ]
361             };
362              
363             require DateTime::Format::Builder;
364             DateTime::Format::Builder->create_class(
365             parsers => {
366             parse_datetime => [
367             $parse_standard,
368             $parse_standard_with_quarter
369             ]
370             }
371             );
372              
373             1;
374              
375             __END__