zeroclickinfo-goodies/lib/DDG/Goodie/NameDays.pm

136 lines
4.3 KiB
Perl
Raw Normal View History

2014-11-06 23:07:09 -08:00
package DDG::Goodie::NameDays;
# ABSTRACT: Display Name Days for a given name or date
2014-11-11 23:46:05 -08:00
use utf8;
2014-11-06 23:07:09 -08:00
use strict;
2015-01-15 22:49:54 -08:00
use warnings;
2014-11-06 23:07:09 -08:00
use DateTime;
2015-01-15 22:49:54 -08:00
use Locale::Country;
2014-11-06 23:07:09 -08:00
use DDG::Goodie;
with 'DDG::GoodieRole::Dates';
2015-01-15 22:49:54 -08:00
zci answer_type => "name_days";
2014-11-06 23:07:09 -08:00
zci is_cached => 1;
# Triggers
2015-02-10 05:15:25 -08:00
triggers any => "name day", "name days", "nameday", "namedays", "imieniny",
"jmeniny", "svátek"; # The phrase "name days" in Polish and Czech language
2014-11-06 23:07:09 -08:00
2014-11-11 23:46:05 -08:00
2014-11-06 23:07:09 -08:00
# Load the data file
my @names = share('preprocessed_names.txt')->slurp(iomode => '<:encoding(UTF-8)', chomp => 1); # Names indexed by day
my %dates = share('preprocessed_dates.txt')->slurp(iomode => '<:encoding(UTF-8)', chomp => 1); # Days indexed by name
2014-11-11 23:46:05 -08:00
sub parse_other_date_formats {
# Quick fix for the date formats not supported by parse_datestring_to_date.
# If parse_datestring_to_date will be improved, you can remove some of the following code.
2015-07-04 07:12:27 -07:00
2014-11-11 23:46:05 -08:00
# US date format ("month/day")
if (/^([0-1]?[0-9])\s?\/\s?([0-3]?[0-9])$/) {
# Suppress errors for invalid dates with eval
return eval { new DateTime(year => 2000, day => $2, month => $1) };
}
2015-07-04 07:12:27 -07:00
2014-11-11 23:46:05 -08:00
# Polish date format ("day.month")
if (/^([0-3]?[0-9])\s?\.\s?([0-1]?[0-9])$/) {
return eval { new DateTime(year => 2000, day => $1, month => $2) };
}
2015-07-04 07:12:27 -07:00
2014-11-11 23:46:05 -08:00
# Polish month names
2014-11-11 23:53:51 -08:00
s/\b(styczeń|stycznia)\b/Jan/i;
s/\b(luty|lutego)\b/Feb/i;
s/\b(marzec|marca)\b/Mar/i;
s/\b(kwiecień|kwietnia)\b/Apr/i;
s/\b(maj|maja)\b/May/i;
s/\b(czerwiec|czerwca)\b/Jun/i;
s/\b(lipiec|lipca)\b/Jul/i;
s/\b(sierpień|sierpnia)\b/Aug/i;
s/\b(wrzesień|września)\b/Sep/i;
s/\b(październik|października)\b/Oct/i;
s/\b(listopad|listopada)\b/Nov/i;
s/\b(grudzień|grudnia)\b/Dec/i;
2015-07-04 07:12:27 -07:00
2014-11-22 07:11:00 -08:00
# Czech month names
s/\b(leden|ledna)\b/Jan/i;
s/\b(únor|února)\b/Feb/i;
s/\b(březen|března)\b/Mar/i;
s/\b(duben|dubna)\b/Apr/i;
s/\b(květen|května)\b/May/i;
s/\b(červen|června)\b/Jun/i;
s/\b(červenec|července)\b/Jul/i;
s/\b(srpen|srpna)\b/Aug/i;
s/\b(září)\b/Sep/i;
s/\b(říjen|října)\b/Oct/i;
s/\b(listopad|listopadu)\b/Nov/i;
s/\b(prosinec|prosince)\b/Dec/i;
2015-07-04 07:12:27 -07:00
2014-11-12 00:04:52 -08:00
# Parse_datestring_to_date uses the current year if the year is not specified, so
# it will not parse "29 Feb" in a non-leap year. Fix this problem here.
if (/^29\s?(?:th)?\s*(Feb|February)/ || /(Feb|February)\s*29\s?(?:th)?$/) {
return new DateTime(year => 2000, day => 29, month => 2);
}
2015-07-04 07:12:27 -07:00
2014-11-11 23:53:51 -08:00
return parse_datestring_to_date($_);
2014-11-11 23:46:05 -08:00
}
2015-01-15 22:49:54 -08:00
sub get_flag {
my $country = shift;
return '<span class="flag-sm flag-sm-' . country2code($country) . '"></span>';
}
2014-11-11 23:46:05 -08:00
2014-11-06 23:07:09 -08:00
# Handle statement
handle remainder => sub {
2014-12-03 21:40:05 -08:00
my $text;
2014-12-08 00:33:49 -08:00
my $html;
2014-12-05 07:11:04 -08:00
my $query;
2015-01-15 22:49:54 -08:00
my $header;
2015-07-04 07:12:27 -07:00
2014-12-03 21:40:05 -08:00
if (exists $dates{lc($_)}) {
# Search by name first
2014-12-05 07:11:04 -08:00
$query = ucfirst($_);
2014-12-08 00:33:49 -08:00
($text, $html) = split('\|', $dates{lc($_)});
2015-01-15 22:49:54 -08:00
$header = 'Name days for <b>' . html_enc($query) . '</b>';
2014-12-03 21:40:05 -08:00
} else {
# Then, search by date
my $day = parse_datestring_to_date($_);
if (!$day) {
$day = parse_other_date_formats($_);
}
return unless $day;
# Any leap year here, because the array includes February, 29
$day->set_year(2000);
2015-07-04 07:12:27 -07:00
my $suffix = 'th';
my $daynum = $day->day();
$suffix = 'st' if $daynum == 1 || $daynum == 21 || $daynum == 31;
$suffix = 'nd' if $daynum == 2 || $daynum == 22;
$suffix = 'rd' if $daynum == 3 || $daynum == 23;
$query = $day->month_name() . " $daynum$suffix";
2014-12-03 21:40:05 -08:00
$text = $names[$day->day_of_year() - 1];
2015-07-04 07:12:27 -07:00
2014-12-08 00:33:49 -08:00
# Convert to HTML
$html = $text;
$html =~ s/(\d{1,2}) (\w{1,3})/$1&nbsp;$2/g;
2015-01-15 22:49:54 -08:00
$html =~ s@(.*?): (.*?)(?:$|; )@'<tr><td class="name-days-country">' . get_flag($1) .
' <span class="name-days-country-name">' . $1 . '</span>' .
'</td><td class="name-days-dates">' . $2 . '</td></tr>'@ge;
2015-07-04 07:12:27 -07:00
2015-01-15 22:49:54 -08:00
$header = 'Name days on <b>' . html_enc($query) . '</b>';
2014-11-11 23:46:05 -08:00
}
2015-07-04 07:12:27 -07:00
2014-12-08 00:33:49 -08:00
# Add the header
2015-08-26 00:26:13 -07:00
$html = '<div class="zci--name_days">' .
'<span>' . $header . '</span>' .
'<div class="zci__content"><table>' .
$html . '</table></div></div>';
2015-07-04 07:12:27 -07:00
2014-12-03 21:40:05 -08:00
return $text, html => $html;
2014-11-06 23:07:09 -08:00
};
1;