File Coverage

blib/lib/DateTime/Locale/FromData.pm
Criterion Covered Total %
statement 115 120 95.8
branch 5 6 83.3
condition 5 10 50.0
subroutine 33 38 86.8
pod 8 24 33.3
total 166 198 83.8


line stmt bran cond sub pod time code
1             package DateTime::Locale::FromData;
2              
3 17     17   873 use strict;
  17         57  
  17         751  
4 17     17   103 use warnings;
  17         35  
  17         1227  
5 17     17   538 use namespace::autoclean;
  17         21168  
  17         152  
6              
7 17     17   10600 use DateTime::Locale::Util qw( parse_locale_code );
  17         81  
  17         1730  
8 17     17   10378 use Params::ValidationCompiler 0.13 qw( validation_for );
  17         523282  
  17         1532  
9 17     17   11505 use Specio::Declare;
  17         1005422  
  17         248  
10 17     17   15379 use Storable qw( dclone );
  17         75670  
  17         4598  
11              
12             our $VERSION = '1.45';
13              
14             my @FormatLengths;
15              
16             BEGIN {
17 17     17   289 my @methods = qw(
18             code
19             name
20             language
21             script
22             territory
23             variant
24             native_name
25             native_language
26             native_script
27             native_territory
28             native_variant
29             am_pm_abbreviated
30             date_format_full
31             date_format_long
32             date_format_medium
33             date_format_short
34             time_format_full
35             time_format_long
36             time_format_medium
37             time_format_short
38             day_format_abbreviated
39             day_format_narrow
40             day_format_wide
41             day_stand_alone_abbreviated
42             day_stand_alone_narrow
43             day_stand_alone_wide
44             month_format_abbreviated
45             month_format_narrow
46             month_format_wide
47             month_stand_alone_abbreviated
48             month_stand_alone_narrow
49             month_stand_alone_wide
50             quarter_format_abbreviated
51             quarter_format_narrow
52             quarter_format_wide
53             quarter_stand_alone_abbreviated
54             quarter_stand_alone_narrow
55             quarter_stand_alone_wide
56             era_abbreviated
57             era_narrow
58             era_wide
59             default_date_format_length
60             default_time_format_length
61             first_day_of_week
62             version
63             glibc_datetime_format
64             glibc_date_format
65             glibc_date_1_format
66             glibc_time_format
67             glibc_time_12_format
68             );
69              
70 17         53 for my $meth (@methods) {
71 850     37119   2984 my $sub = sub { $_[0]->{$meth} };
  37119         8821658  
72             ## no critic (TestingAndDebugging::ProhibitNoStrict)
73 17     17   196 no strict 'refs';
  17         305  
  17         3128  
74 850         1228 *{$meth} = $sub;
  850         3347  
75             }
76              
77 17         62 @FormatLengths = qw( short medium long full );
78              
79 17         38 for my $length (@FormatLengths) {
80 68         117 my $meth = 'datetime_format_' . $length;
81 68         165 my $key = 'computed_' . $meth;
82              
83             my $sub = sub {
84 6     6   25 my $self = shift;
85              
86 6 100       22 return $self->{$key} if exists $self->{$key};
87              
88 5         18 return $self->{$key} = $self->_make_datetime_format($length);
89 68         427 };
90              
91             ## no critic (TestingAndDebugging::ProhibitNoStrict)
92 17     17   140 no strict 'refs';
  17         158  
  17         2239  
93 68         107 *{$meth} = $sub;
  68         29744  
94             }
95             }
96              
97             sub new {
98 1127     1127 0 3114 my $class = shift;
99 1127         2626 my $data = shift;
100              
101             return bless {
102 1127         2235 %{$data},
  1127         44946  
103             default_date_format_length => 'medium',
104             default_time_format_length => 'medium',
105             locale_data => $data
106             }, $class;
107             }
108              
109             sub date_format_default {
110 2     2 0 8 return $_[0]->date_format_medium;
111             }
112              
113             sub time_format_default {
114 2     2 0 6 return $_[0]->time_format_medium;
115             }
116              
117             sub datetime_format {
118 0     0 0 0 return $_[0]->{datetime_format_medium};
119             }
120              
121             sub datetime_format_default {
122 2     2 0 25 return $_[0]->datetime_format_medium;
123             }
124              
125             sub _make_datetime_format {
126 5     5   8 my $self = shift;
127 5         8 my $length = shift;
128              
129 5         11 my $dt_key = 'datetime_format_' . $length;
130 5         11 my $date_meth = 'date_format_' . $length;
131 5         9 my $time_meth = 'time_format_' . $length;
132              
133 5         13 my $dt_format = $self->{$dt_key};
134 5         26 $dt_format =~ s/\{0\}/$self->$time_meth/eg;
  5         14  
135 5         16 $dt_format =~ s/\{1\}/$self->$date_meth/eg;
  5         16  
136              
137 5         55 return $dt_format;
138             }
139              
140             my $length = enum( values => [qw( full long medium short )] );
141             my $validator = validation_for(
142             name => '_check_length_parameter',
143             name_is_optional => 1,
144             params => [ { type => $length } ],
145             );
146              
147             sub set_default_date_format_length {
148 1     1 0 2 my $self = shift;
149 1         29 my ($l) = $validator->(@_);
150              
151 1         13 $self->{default_date_format_length} = lc $l;
152             }
153              
154             sub set_default_time_format_length {
155 1     1 0 2 my $self = shift;
156 1         14 my ($l) = $validator->(@_);
157              
158 1         7 $self->{default_time_format_length} = lc $l;
159             }
160              
161             sub date_formats {
162 1080     1080 0 2185 my %formats;
163 1080         3644 for my $length (@FormatLengths) {
164 4320         7871 my $meth = 'date_format_' . $length;
165 4320         13381 $formats{$length} = $_[0]->$meth;
166             }
167 1080         5787 return \%formats;
168             }
169              
170             sub time_formats {
171 1080     1080 0 2365 my %formats;
172 1080         3818 for my $length (@FormatLengths) {
173 4320         7459 my $meth = 'time_format_' . $length;
174 4320         13828 $formats{$length} = $_[0]->$meth;
175             }
176 1080         5680 return \%formats;
177             }
178              
179             sub available_formats {
180 2     2 1 920 my $self = shift;
181              
182             $self->{computed_available_formats}
183 2   50     15 ||= [ sort keys %{ $self->_available_formats } ];
  2         8  
184              
185 2         8 return @{ $self->{computed_available_formats} };
  2         152  
186             }
187              
188             sub format_for {
189 109     109 1 45626 my $self = shift;
190 109         223 my $for = shift;
191              
192 109         200 return $self->_available_formats->{$for};
193             }
194              
195 111     111   616 sub _available_formats { $_[0]->{available_formats} }
196              
197             sub prefers_24_hour_time {
198 8     8 1 49 my $self = shift;
199              
200             return $self->{prefers_24_hour_time}
201 8 50       25 if exists $self->{prefers_24_hour_time};
202              
203             # This regex splits the pattern into parts, but only keeps the parts that aren't quoted. This
204             # lets us ignore literal strings in the pattern when looking for `h|K`. Without this we could
205             # match on a literal `'h'` in the pattern (which fr-CA has at the time of this writing), giving
206             # us a false positive.
207 8         22 my @parts = split /(?:'(?:(?:[^']|'')*)')/, $self->time_format_short;
208 8         19 return $self->{prefers_24_hour_time} = !( grep {/h|K/} @parts );
  9         99  
209             }
210              
211             sub language_code {
212 2     2 1 16 my $self = shift;
213             return ( $self->{parsed_code} ||= { parse_locale_code( $self->code ) } )
214 2   50     17 ->{language};
215             }
216              
217             sub script_code {
218 2     2 1 1050 my $self = shift;
219             return ( $self->{parsed_code} ||= { parse_locale_code( $self->code ) } )
220 2   50     18 ->{script};
221             }
222              
223             sub territory_code {
224 3     3 1 549 my $self = shift;
225             return ( $self->{parsed_code} ||= { parse_locale_code( $self->code ) } )
226 3   50     24 ->{territory};
227             }
228              
229             sub variant_code {
230 2     2 1 13 my $self = shift;
231             return ( $self->{parsed_code} ||= { parse_locale_code( $self->code ) } )
232 2   50     15 ->{variant};
233             }
234              
235             sub id {
236 1     1 0 466 $_[0]->code;
237             }
238              
239             sub language_id {
240 0     0 0 0 $_[0]->language_code;
241             }
242              
243             sub script_id {
244 0     0 0 0 $_[0]->script_code;
245             }
246              
247             sub territory_id {
248 0     0 0 0 $_[0]->territory_code;
249             }
250              
251             sub variant_id {
252 0     0 0 0 $_[0]->variant_code;
253             }
254              
255             sub locale_data {
256 3     3 1 247 return %{ dclone( $_[0]->{locale_data} ) };
  3         802  
257             }
258              
259             sub STORABLE_freeze {
260 2     2 0 83 my $self = shift;
261 2         6 my $cloning = shift;
262              
263 2 100       315 return if $cloning;
264              
265 1         5 return $self->code;
266             }
267              
268             sub STORABLE_thaw {
269 2     2 0 7851 my $self = shift;
270 2         5 shift;
271 2         7 my $serialized = shift;
272              
273 2         662 require DateTime::Locale;
274 2         25 my $obj = DateTime::Locale->load($serialized);
275              
276 2         8 %{$self} = %{$obj};
  2         41  
  2         26  
277              
278 2         36 return $self;
279             }
280              
281             1;
282              
283             # ABSTRACT: Class for locale objects instantiated from pre-defined data
284              
285             __END__
286              
287             =pod
288              
289             =encoding UTF-8
290              
291             =head1 NAME
292              
293             DateTime::Locale::FromData - Class for locale objects instantiated from pre-defined data
294              
295             =head1 VERSION
296              
297             version 1.45
298              
299             =head1 SYNOPSIS
300              
301             my $locale = DateTime::Locale::FromData->new(%lots_of_data)
302              
303             =head1 DESCRIPTION
304              
305             This class is used to represent locales instantiated from the data in the
306             DateTime::Locale::Data module.
307              
308             =head1 METHODS
309              
310             This class provides the following methods:
311              
312             =head2 $locale->code
313              
314             The complete locale id, something like "en-US".
315              
316             =head2 $locale->language_code
317              
318             The language portion of the code, like "en".
319              
320             =head2 $locale->script_code
321              
322             The script portion of the code, like "Hant".
323              
324             =head2 $locale->territory_code
325              
326             The territory portion of the code, like "US".
327              
328             =head2 $locale->variant_code
329              
330             The variant portion of the code, like "POSIX".
331              
332             =head2 $locale->name
333              
334             The locale's complete name, which always includes at least a language
335             component, plus optional territory and variant components. Something like
336             "English United States". The value returned will always be in English.
337              
338             =head2 $locale->language
339              
340             =head2 $locale->script
341              
342             =head2 $locale->territory
343              
344             =head2 $locale->variant
345              
346             The relevant component from the locale's complete name, like "English" or
347             "United States".
348              
349             =head2 $locale->native_name
350              
351             The locale's complete name in localized form as a UTF-8 string.
352              
353             =head2 $locale->native_language
354              
355             =head2 $locale->native_script
356              
357             =head2 $locale->native_territory
358              
359             =head2 $locale->native_variant
360              
361             The relevant component from the locale's complete native name as a UTF-8
362             string.
363              
364             =head2 $locale->month_format_wide
365              
366             =head2 $locale->month_format_abbreviated
367              
368             =head2 $locale->month_format_narrow
369              
370             =head2 $locale->month_stand_alone_wide
371              
372             =head2 $locale->month_stand_alone_abbreviated
373              
374             =head2 $locale->month_stand_alone_narrow
375              
376             =head2 $locale->day_format_wide
377              
378             =head2 $locale->day_format_abbreviated
379              
380             =head2 $locale->day_format_narrow
381              
382             =head2 $locale->day_stand_alone_wide
383              
384             =head2 $locale->day_stand_alone_abbreviated
385              
386             =head2 $locale->day_stand_alone_narrow
387              
388             =head2 $locale->quarter_format_wide
389              
390             =head2 $locale->quarter_format_abbreviated
391              
392             =head2 $locale->quarter_format_narrow
393              
394             =head2 $locale->quarter_stand_alone_wide
395              
396             =head2 $locale->quarter_stand_alone_abbreviated
397              
398             =head2 $locale->quarter_stand_alone_narrow
399              
400             =head2 $locale->am_pm_abbreviated
401              
402             =head2 $locale->era_wide
403              
404             =head2 $locale->era_abbreviated
405              
406             =head2 $locale->era_narrow
407              
408             These methods all return an array reference containing the specified data.
409              
410             The methods with "format" in the name should return strings that can be used a
411             part of a string, like "the month of July". The stand alone values are for use
412             in things like calendars as opposed to a sentence.
413              
414             The narrow forms may not be unique (for example, in the day column heading for
415             a calendar it's okay to have "T" for both Tuesday and Thursday).
416              
417             The wide name should always be the full name of thing in question. The narrow
418             name should be just one or two characters.
419              
420             B<These methods return a reference to the data stored in the locale object. If
421             you change this reference's contents, this will affect the data in the locale
422             object! You should clone the data first if you want to modify it.>
423              
424             =head2 $locale->date_format_full
425              
426             =head2 $locale->date_format_long
427              
428             =head2 $locale->date_format_medium
429              
430             =head2 $locale->date_format_short
431              
432             =head2 $locale->time_format_full
433              
434             =head2 $locale->time_format_long
435              
436             =head2 $locale->time_format_medium
437              
438             =head2 $locale->time_format_short
439              
440             =head2 $locale->datetime_format_full
441              
442             =head2 $locale->datetime_format_long
443              
444             =head2 $locale->datetime_format_medium
445              
446             =head2 $locale->datetime_format_short
447              
448             These methods return strings appropriate for the C<< DateTime->format_cldr >>
449             method.
450              
451             =head2 $locale->format_for($name)
452              
453             These are accessed by passing a name to C<< $locale->format_for(...) >>, where
454             the name is a CLDR-style format specifier.
455              
456             The return value is a string suitable for passing to C<< $dt->format_cldr >>,
457             so you can do something like this:
458              
459             print $dt->format_cldr( $dt->locale->format_for('MMMdd') )
460              
461             which for the "en" locale would print out something like "08 Jul".
462              
463             Note that the localization may also include additional text specific to the
464             locale. For example, the "MMMMd" format for the "zh" locale includes the
465             Chinese characters for "day" (日) and month (月), so you get something like
466             "S<8月23日>".
467              
468             =head2 $locale->available_formats
469              
470             This should return a list of all the format names that could be passed to C<<
471             $locale->format_for >>.
472              
473             See the documentation for individual locales for details and examples of these
474             formats. The format names that are available vary by locale.
475              
476             =head2 $locale->glibc_datetime_format
477              
478             =head2 $locale->glibc_date_format
479              
480             =head2 $locale->glibc_date_1_format
481              
482             =head2 $locale->glibc_time_format
483              
484             =head2 $locale->glibc_time_12_format
485              
486             These methods return strings appropriate for the C<< DateTime->strftime >>
487             method. However, you are strongly encouraged to use the other format methods,
488             which use the CLDR format data. They are primarily included for the benefit for
489             L<DateTime::Format::Strptime>.
490              
491             =head2 $locale->version
492              
493             The CLDR version from which this locale was generated.
494              
495             =head2 $locale->prefers_24_hour_time
496              
497             Returns a boolean indicating whether or not the locale prefers 24-hour time.
498              
499             =head2 $locale->first_day_of_week
500              
501             Returns a number from 1 to 7 indicating the I<local> first day of the week,
502             with Monday being 1 and Sunday being 7.
503              
504             =head2 $locale->locale_data
505              
506             Returns a clone of the original data used to create this locale as a hash. This
507             is here to facilitate creating custom locales via
508             C<DateTime::Locale->register_data_locale>.
509              
510             =head1 SUPPORT
511              
512             Bugs may be submitted at L<https://github.com/houseabsolute/DateTime-Locale/issues>.
513              
514             There is a mailing list available for users of this distribution,
515             L<mailto:datetime@perl.org>.
516              
517             =head1 SOURCE
518              
519             The source code repository for DateTime-Locale can be found at L<https://github.com/houseabsolute/DateTime-Locale>.
520              
521             =head1 AUTHOR
522              
523             Dave Rolsky <autarch@urth.org>
524              
525             =head1 COPYRIGHT AND LICENSE
526              
527             This software is copyright (c) 2003 - 2025 by Dave Rolsky.
528              
529             This is free software; you can redistribute it and/or modify it under
530             the same terms as the Perl 5 programming language system itself.
531              
532             The full text of the license can be found in the
533             F<LICENSE> file included with this distribution.
534              
535             =cut