1use strict; 2use warnings; 3use utf8; 4 5use File::Spec; 6use Test::More; 7 8use DateTime::Locale; 9 10my @locale_ids = sort DateTime::Locale->ids(); 11my %locale_names = map { $_ => 1 } DateTime::Locale->names; 12my %locale_ids = map { $_ => 1 } DateTime::Locale->ids; 13 14plan tests => 15 5 # starting 16 + 1 # one test for root locale 17 + ( ( @locale_ids - 1 ) * 21 ) # tests for each other local 18 + 56 # check_root 19 + 24 # check_en 20 + 66 # check_en_GB 21 + 23 # check_en_US 22 + 11 # check_es_ES 23 + 5 # check_en_US_POSIX 24 + 2 # check_af 25 + 9 # check_DT_Lang 26 ; 27 28{ 29 ok( @locale_ids >= 240, 'Coverage looks complete' ); 30 ok( $locale_names{English}, "Locale name 'English' found" ); 31 ok( $locale_ids{ar_JO}, "Locale id 'ar_JO' found" ); 32 33 eval { DateTime::Locale->load('Does not exist') }; 34 like( $@, qr/invalid/i, 35 'invalid locale name/id to load() causes an error' ); 36 37 # this type of locale id should work 38 my $l = DateTime::Locale->load('en_US.LATIN-1'); 39 is( $l->id, 'en_US', 'id is en_US' ); 40} 41 42# testing the basics for all ids 43{ 44 for my $locale_id (@locale_ids) { 45 my $locale = eval { DateTime::Locale->load($locale_id) }; 46 47 isa_ok( $locale, 'DateTime::Locale::Base' ); 48 49 next if $locale_id eq 'root'; 50 51 ok( $locale_ids{ $locale->id() }, 52 "'$locale_id': Has a valid locale id" ); 53 54 ok( length $locale->name(), "'$locale_id': Has a locale name" ); 55 ok( 56 length $locale->native_name(), 57 "'$locale_id': Has a native locale name" 58 ); 59 60 for my $test ( 61 { 62 locale_method => 'month_format_wide', 63 count => 12, 64 }, { 65 locale_method => 'month_format_abbreviated', 66 count => 12, 67 }, { 68 locale_method => 'day_format_wide', 69 count => 7, 70 }, { 71 locale_method => 'day_format_abbreviated', 72 count => 7, 73 }, { 74 locale_method => 'quarter_format_wide', 75 count => 4, 76 }, { 77 locale_method => 'quarter_format_abbreviated', 78 count => 4, 79 }, { 80 locale_method => 'am_pm_abbreviated', 81 count => 2, 82 }, { 83 locale_method => 'era_wide', 84 count => 2, 85 }, { 86 locale_method => 'era_abbreviated', 87 count => 2, 88 }, 89 ) { 90 check_array( locale => $locale, %$test ); 91 } 92 93 # We can't actually expect these to be unique. 94 is( scalar @{ $locale->day_format_narrow() }, 7, 95 'day_format_narrow() returns 7 items' ); 96 is( scalar @{ $locale->month_format_narrow() }, 12, 97 'month_format_narrow() returns 12 items' ); 98 is( scalar @{ $locale->day_stand_alone_narrow() }, 7, 99 'day_stand_alone_narrow() returns 7 items' ); 100 is( scalar @{ $locale->month_stand_alone_narrow() }, 12, 101 'month_stand_alone_narrow() returns 12 items' ); 102 103 check_formats( $locale_id, $locale, 'date_formats', 'date_format' ); 104 check_formats( $locale_id, $locale, 'time_formats', 'time_format' ); 105 } 106} 107 108check_root(); 109check_en(); 110check_en_GB(); 111check_en_US(); 112check_es_ES(); 113check_en_US_POSIX(); 114check_af(); 115check_DT_Lang(); 116 117sub check_array { 118 my %test = @_; 119 120 my $locale_method = $test{locale_method}; 121 122 my %unique = map { $_ => 1 } @{ $test{locale}->$locale_method() }; 123 124 my $locale_id = $test{locale}->id(); 125 126TODO: 127 { 128 local $TODO 129 = 'The ii locale does not have unique abbreviated days for some reason' 130 if $test{locale}->id() =~ /^ii/ 131 && $locale_method eq 'day_format_abbreviated'; 132 133 is( 134 keys %unique, $test{count}, 135 qq{'$locale_id': '$locale_method' contains $test{count} unique items} 136 ); 137 } 138} 139 140sub check_formats { 141 my ( $locale_id, $locale, $hash_func, $item_func ) = @_; 142 143 my %unique = map { $_ => 1 } values %{ $locale->$hash_func() }; 144 145 ok( keys %unique >= 1, 146 "'$locale_id': '$hash_func' contains at least 1 unique item" ); 147 148 foreach my $length (qw( full long medium short )) { 149 my $method = $item_func . q{_} . $length; 150 151 my $val = $locale->$method(); 152 153 if ( defined $val ) { 154 delete $unique{$val}; 155 } 156 else { 157 Test::More::diag("$locale_id returned undef for $method()"); 158 } 159 } 160 161 is( 162 keys %unique, 0, 163 "'$locale_id': Data returned by '$hash_func' and '$item_func patterns' matches" 164 ); 165} 166 167sub check_root { 168 my $locale = DateTime::Locale->load('root'); 169 170 my %tests = ( 171 day_format_wide => [qw( 2 3 4 5 6 7 1 )], 172 173 day_format_abbreviated => [qw( 2 3 4 5 6 7 1 )], 174 175 day_format_narrow => [qw( 2 3 4 5 6 7 1 )], 176 177 day_stand_alone_wide => [qw( 2 3 4 5 6 7 1 )], 178 179 day_stand_alone_abbreviated => [qw( 2 3 4 5 6 7 1 )], 180 181 day_stand_alone_narrow => [qw( 2 3 4 5 6 7 1 )], 182 183 month_format_wide => [qw( 1 2 3 4 5 6 7 8 9 10 11 12 )], 184 185 month_format_abbreviated => [qw( 1 2 3 4 5 6 7 8 9 10 11 12 )], 186 187 month_format_narrow => [qw( 1 2 3 4 5 6 7 8 9 10 11 12 )], 188 189 month_stand_alone_wide => [qw( 1 2 3 4 5 6 7 8 9 10 11 12 )], 190 191 month_stand_alone_abbreviated => [qw( 1 2 3 4 5 6 7 8 9 10 11 12 )], 192 193 month_stand_alone_narrow => [qw( 1 2 3 4 5 6 7 8 9 10 11 12 )], 194 195 quarter_format_wide => [qw( Q1 Q2 Q3 Q4 )], 196 197 quarter_format_abbreviated => [qw( Q1 Q2 Q3 Q4 )], 198 199 quarter_format_narrow => [qw( 1 2 3 4 )], 200 201 quarter_stand_alone_wide => [qw( Q1 Q2 Q3 Q4 )], 202 203 quarter_stand_alone_abbreviated => [qw( Q1 Q2 Q3 Q4 )], 204 205 quarter_stand_alone_narrow => [qw( 1 2 3 4 )], 206 207 era_wide => [qw( BCE CE )], 208 209 era_abbreviated => [qw( BCE CE )], 210 211 era_narrow => [qw( BCE CE )], 212 213 am_pm_abbreviated => [qw( AM PM )], 214 215 datetime_format_full => 'EEEE, y MMMM dd HH:mm:ss zzzz', 216 datetime_format_long => 'y MMMM d HH:mm:ss z', 217 datetime_format_medium => 'y MMM d HH:mm:ss', 218 datetime_format_short => 'yyyy-MM-dd HH:mm', 219 220 datetime_format_default => 'y MMM d HH:mm:ss', 221 222 glibc_datetime_format => '%a %b %e %H:%M:%S %Y', 223 glibc_date_format => '%m/%d/%y', 224 glibc_time_format => '%H:%M:%S', 225 226 first_day_of_week => 1, 227 228 prefers_24_hour_time => 1, 229 ); 230 231 test_data( $locale, %tests ); 232 233 my %formats = ( 234 d => 'd', 235 EEEd => 'd EEE', 236 hm => 'h:mm a', 237 Hm => 'H:mm', 238 hms => 'h:mm:ss a', 239 Hms => 'H:mm:ss', 240 M => 'L', 241 Md => 'M-d', 242 MEd => 'E, M-d', 243 MMM => 'LLL', 244 MMMd => 'MMM d', 245 MMMEd => 'E MMM d', 246 MMMMd => 'MMMM d', 247 MMMMEd => 'E MMMM d', 248 ms => 'mm:ss', 249 y => 'y', 250 yM => 'y-M', 251 yMEd => 'EEE, y-M-d', 252 yMMM => 'y MMM', 253 yMMMEd => 'EEE, y MMM d', 254 yMMMM => 'y MMMM', 255 yQ => 'y Q', 256 yQQQ => 'y QQQ', 257 ); 258 259 test_formats( $locale, %formats ); 260} 261 262sub check_en { 263 my $locale = DateTime::Locale->load('en'); 264 265 my %tests = ( 266 en_data(), 267 268 name => 'English', 269 ); 270 271 test_data( $locale, %tests ); 272} 273 274sub check_en_GB { 275 my $locale = DateTime::Locale->load('en_GB'); 276 277 my %tests = ( 278 en_data(), 279 280 first_day_of_week => 7, 281 282 name => 'English United Kingdom', 283 native_name => 'English United Kingdom', 284 language => 'English', 285 native_language => 'English', 286 territory => 'United Kingdom', 287 native_territory => 'United Kingdom', 288 variant => undef, 289 native_variant => undef, 290 291 language_id => 'en', 292 territory_id => 'GB', 293 variant_id => undef, 294 295 glibc_datetime_format => '%a %d %b %Y %T %Z', 296 glibc_date_format => '%d/%m/%y', 297 glibc_time_format => '%T', 298 299 datetime_format_default => 'd MMM y HH:mm:ss', 300 ); 301 302 test_data( $locale, %tests ); 303 304 my %formats = ( 305 Md => 'd/M', 306 MEd => 'E, d/M', 307 MMdd => 'dd/MM', 308 MMMEd => 'E d MMM', 309 MMMMd => 'd MMMM', 310 yMEd => 'EEE, d/M/yyyy', 311 yyMMM => 'MMM yy', 312 yyyyMM => 'MM/yyyy', 313 yyyyMMMM => 'MMMM y', 314 315 # from en 316 d => 'd', 317 EEEd => 'd EEE', 318 hm => 'h:mm a', 319 Hm => 'H:mm', 320 Hms => 'H:mm:ss', 321 M => 'L', 322 MMM => 'LLL', 323 MMMd => 'MMM d', 324 MMMMEd => 'E, MMMM d', 325 ms => 'mm:ss', 326 y => 'y', 327 yM => 'M/yyyy', 328 yMMM => 'MMM y', 329 yMMMEd => 'EEE, MMM d, y', 330 yMMMM => 'MMMM y', 331 yQ => 'Q yyyy', 332 yQQQ => 'QQQ y', 333 334 # from root 335 hms => 'h:mm:ss a', 336 ); 337 338 test_formats( $locale, %formats ); 339} 340 341sub check_en_US { 342 my $locale = DateTime::Locale->load('en_US'); 343 344 my %tests = ( 345 en_data(), 346 347 first_day_of_week => 7, 348 ); 349 350 test_data( $locale, %tests ); 351} 352 353sub en_data { 354 return ( 355 day_format_wide => 356 [qw( Monday Tuesday Wednesday Thursday Friday Saturday Sunday )], 357 358 day_format_abbreviated => [qw( Mon Tue Wed Thu Fri Sat Sun )], 359 360 day_format_narrow => [qw( M T W T F S S )], 361 362 day_stand_alone_wide => 363 [qw( Monday Tuesday Wednesday Thursday Friday Saturday Sunday )], 364 365 day_stand_alone_abbreviated => [qw( Mon Tue Wed Thu Fri Sat Sun )], 366 367 day_stand_alone_narrow => [qw( M T W T F S S )], 368 369 month_format_wide => [ 370 qw( January February March April May June 371 July August September October November December ) 372 ], 373 374 month_format_abbreviated => 375 [qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec )], 376 377 month_format_narrow => [qw( J F M A M J J A S O N D )], 378 379 month_stand_alone_wide => [ 380 qw( January February March April May June 381 July August September October November December ) 382 ], 383 384 month_stand_alone_abbreviated => 385 [qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec )], 386 387 month_stand_alone_narrow => [qw( J F M A M J J A S O N D )], 388 389 quarter_format_wide => 390 [ '1st quarter', '2nd quarter', '3rd quarter', '4th quarter' ], 391 392 quarter_format_abbreviated => [qw( Q1 Q2 Q3 Q4 )], 393 394 quarter_format_narrow => [qw( 1 2 3 4 )], 395 396 quarter_stand_alone_wide => 397 [ '1st quarter', '2nd quarter', '3rd quarter', '4th quarter' ], 398 399 quarter_stand_alone_abbreviated => [qw( Q1 Q2 Q3 Q4 )], 400 401 quarter_stand_alone_narrow => [qw( 1 2 3 4 )], 402 403 era_wide => [ 'Before Christ', 'Anno Domini' ], 404 405 era_abbreviated => [qw( BC AD )], 406 407 era_narrow => [qw( B A )], 408 409 am_pm_abbreviated => [qw( AM PM )], 410 411 first_day_of_week => 1, 412 ); 413} 414 415sub test_data { 416 my $locale = shift; 417 my %tests = @_; 418 419 for my $k ( sort keys %tests ) { 420 my $desc = "$k for " . $locale->id(); 421 if ( ref $tests{$k} ) { 422 is_deeply( $locale->$k(), $tests{$k}, $desc ); 423 } 424 else { 425 is( $locale->$k(), $tests{$k}, $desc ); 426 } 427 } 428} 429 430sub test_formats { 431 my $locale = shift; 432 my %formats = @_; 433 434 for my $name ( keys %formats ) { 435 is( 436 $locale->format_for($name), $formats{$name}, 437 "Format for $name with " . $locale->id() 438 ); 439 } 440 441 is_deeply( 442 [ $locale->available_formats() ], 443 [ sort keys %formats ], 444 "Available formats for " . $locale->id() . " match what is expected" 445 ); 446} 447 448sub check_es_ES { 449 my $locale = DateTime::Locale->load('es_ES'); 450 451 is( $locale->name(), 'Spanish Spain', 'name()' ); 452 is( $locale->native_name(), 'español España', 'native_name()' ); 453 is( $locale->language(), 'Spanish', 'language()' ); 454 is( $locale->native_language(), 'español', 'native_language()' ); 455 is( $locale->territory(), 'Spain', 'territory()' ); 456 is( $locale->native_territory(), 'España', 'native_territory()' ); 457 is( $locale->variant(), undef, 'variant()' ); 458 is( $locale->native_variant(), undef, 'native_variant()' ); 459 460 is( $locale->language_id(), 'es', 'language_id()' ); 461 is( $locale->territory_id(), 'ES', 'territory_id()' ); 462 is( $locale->variant_id(), undef, 'variant_id()' ); 463} 464 465sub check_af { 466 my $locale = DateTime::Locale->load('af'); 467 468 is_deeply( 469 $locale->month_format_abbreviated(), 470 [qw( Jan Feb Mar Apr Mei Jun Jul Aug Sep Okt Nov Des )], 471 'month abbreviations for af use non-draft form' 472 ); 473 474 is_deeply( 475 $locale->month_format_narrow(), 476 [ 1 .. 12 ], 477 'month narrows for af use draft form because that is the only form available' 478 ); 479} 480 481sub check_en_US_POSIX { 482 my $locale = DateTime::Locale->load('en_US_POSIX'); 483 484 is( $locale->variant(), 'Computer', 'variant()' ); 485 is( $locale->native_variant(), 'Computer', 'native_variant()' ); 486 487 is( $locale->language_id(), 'en', 'language_id()' ); 488 is( $locale->territory_id(), 'US', 'territory_id()' ); 489 is( $locale->variant_id(), 'POSIX', 'variant_id()' ); 490} 491 492sub check_DT_Lang { 493 foreach my $old ( 494 qw ( Austrian TigrinyaEthiopian TigrinyaEritrean 495 Brazilian Portuguese 496 Afar Sidama Tigre ) 497 ) { 498 ok( DateTime::Locale->load($old), 499 "backwards compatibility for $old" ); 500 } 501 502 foreach my $old (qw ( Gedeo )) { 503 SKIP: 504 { 505 skip 506 'No CLDR XML data for some African languages included in DT::Language', 507 1 508 unless $locale_names{$old}; 509 510 ok( DateTime::Locale->load($old), 511 "backwards compatibility for $old" ); 512 } 513 } 514} 515 516