package Date::Verify;
use strict;
use warnings;
use Exporter qw(import);
our @EXPORT = qw(four_digit_year month_name month_number day_number);
use Data::Validate qw(is_integer is_between);
use Date::Calc qw(:all);
sub four_digit_year {
my $year = shift;
if ($year !~ /\d{4}/) {
die "Sorry, please use the four digit year. Stopped";
}
return $year;
}
sub month_name {
my ($month) = @_;
if (is_integer($month)) {
if (is_between($month, 1, 12)) {
$month = Month_to_Text($month);
}
else {
die "Sorry, the month number you entered is invalid. Stopped";
}
}
else {
my $decoded_month = Decode_Month($month);
if ( $decoded_month ) {
$month = Month_to_Text($decoded_month);
}
else {
die "Sorry, your month name is a little short. Stopped";
}
}
return $month;
}
sub month_number {
my ($month) = @_;
if (is_integer($month)) {
if (is_between($month, 1, 12)) {
$month = $month;
}
else {
die "Sorry, the month number you entered is invalid. Stopped";
}
}
else {
my $decoded_month = Decode_Month($month);
if ( $decoded_month ) {
$month = $decoded_month;
}
else {
die "Sorry, your month name is a little short. Stopped";
}
}
return $month;
}
sub day_number {
my ($year, $month, $day) = @_;
my $days = Days_in_Month($year, month_number($month));
if ($day > $days) {
die "Sorry, there are only $days days in $month $year. Stopped";
}
return $day;
}
1;
####
#!/usr/bin/perl
use strict;
use warnings;
use Data::Validate qw(is_integer is_between);
use Date::Calc qw(:all);
use File::Basename;
use Lingua::EN::Inflect qw(ORD);
use lib 'lib';
use Date::Verify qw(four_digit_year month_name month_number day_number);
# commify, round, and pretty_number all make my numbers more readable.
# commify was found in the perldocs to put commas in numbers.
sub commify {
local $_ = shift;
1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
return $_;
}
my ($name, $birth_month, $birth_day, $birth_year) = @ARGV;
chomp(@ARGV);
if (!@ARGV || lc $name eq 'help') {
my $file = basename($0);
print "Please enter a single name and birthday: $file name month day year\n";
}
else {
$birth_year = four_digit_year($birth_year);
$birth_month = month_number($birth_month);
$birth_day = day_number($birth_year, $birth_month, $birth_day);
my $birth_month_name = month_name($birth_month);
my $year = (localtime)[5] + 1900;
my $month = (localtime)[4] + 1;
my $day = (localtime)[3];
# The following counts how many birthdays there has been.
# It also figures out the next year for a birthday.
# I'm still working on the kinks in the next birthday.
my $birthdays;
my $next_year;
if ($birth_month > $month) {
$birthdays = $year - $birth_year - 1;
$next_year = $year;
}
elsif ($birth_month < $month) {
$birthdays = $year - $birth_year - 1;
$next_year = $year + 1;
}
else {
if ($birth_day > $day) {
$birthdays = $year - $birth_year - 1;
$next_year = $year;
}
else {
$birthdays = $year - $birth_year;
$next_year = $year + 1;
}
}
my @birth = ($birth_year, $birth_month, $birth_day);
my @next_bday = ($next_year, $birth_month, $birth_day);
my @today = ($year, $month, $day);
my $days_alive = Delta_Days(@birth,@today);
my $days_til_next_bday = Delta_Days(@today,@next_bday);
my $unbirthdays = $days_alive - $birthdays;
my $unbirthday_text;
if ($month == $birth_month && $day == $birth_day) {
my $birthday = ORD($year - $birth_year);
$unbirthday_text = "Happy $birthday birthday";
}
elsif ($unbirthdays > 0) {
my $ord_unbirthdays = commify(ORD($unbirthdays));
$unbirthday_text = "Happy $ord_unbirthdays unbirthday";
}
else {
$unbirthday_text = "Tomorrow is your first unbirthday";
}
print "$unbirthday_text, $name! You have $days_til_next_bday days until your next birthday on $birth_month_name $birth_day, $next_year.\n";
}
####
#!/usr/bin/perl
use strict;
use warnings FATAL => qw( all );
use Data::Validate qw(is_integer is_between);
use Date::Calc qw(:all);
use File::Basename;
use String::Util qw(trim);
use lib 'lib';
use Date::Verify qw(four_digit_year month_name month_number day_number);
my $month_items;
my $day_stones;
my $zodiac;
my $inc;
while () {
chomp($_);
$inc++ if (!$inc || !$_);
if ( $inc == 1 && $_) {
my ($month, $stone, $us_flower, $bi_flower) = split(/\|/, $_);
$month = trim($month);
$month_items->{$month}{stone} = trim($stone);
$month_items->{$month}{flower}{US} = trim($us_flower);
$month_items->{$month}{flower}{UK} = trim($bi_flower);
}
if ( $inc == 2 && $_ ) {
my ($day, $stone) = split(/\|/, $_);
$day_stones->{trim($day)} = $stone;
}
if ( $inc == 3 && $_ ) {
my ($sign, $start_month, $start_day, $end_month, $end_day, $stone) = split(/\|/, $_);
$sign = trim($sign);
$zodiac->{$sign}{name} = $sign;
$zodiac->{$sign}{start_month} = trim($start_month);
$zodiac->{$sign}{start_day} = $start_day;
$zodiac->{$sign}{end_month} = trim($end_month);
$zodiac->{$sign}{end_day} = $end_day;
$zodiac->{$sign}{stone} = $stone;
}
}
# commify, round, and pretty_number all make my numbers more readable.
# commify was found in the perldocs to put commas in numbers.
sub commify {
local $_ = shift;
1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
return $_;
}
sub month_stone {
my ($month) = @_;
$month = month_name($month);
return $month_items->{$month}{stone};
}
sub month_flower {
my ($month, $country) = @_;
$month = month_name($month);
return $month_items->{$month}{flower}{$country};
}
sub day_stone {
my ($year, $month, $day) = @_;
$month = month_number($month);
my $dow = Day_of_Week($year, $month, $day);
my $day_word = Day_of_Week_to_Text($dow);
return $day_stones->{$day_word};
}
sub sign {
my ($month, $day) = @_;
$month = month_name($month);
my $sign_name;
for my $base_sign (keys %$zodiac) {
my $sign = $zodiac->{$base_sign};
if (($month eq $sign->{start_month} && $day >= $sign->{start_day}) || ($month eq $sign->{end_month} && $day <= $sign->{end_day})) {
$sign_name = $sign->{name};
}
}
return $sign_name;
}
sub sign_stone {
my ($sign) = @_;
return $zodiac->{$sign}{stone};
}
my ($name, $birth_month, $birth_day, $birth_year) = @ARGV;
chomp(@ARGV);
if (!@ARGV) {
my $file = basename($0);
print "Please enter a single name and birthday ($file name month day year).\n";
}
else {
$birth_year = four_digit_year($birth_year);
$birth_month = month_name($birth_month);
$birth_day = day_number($birth_year, $birth_month, $birth_day);
my $birthday = "$birth_month $birth_day, $birth_year";
my $sign_name = sign($birth_month, $birth_day);
$birthday .= " ($sign_name)" if $sign_name;
my $month_stone = month_stone($birth_month);
my $month_flower_US = month_flower($birth_month, 'US');
my $month_flower_UK = month_flower($birth_month, 'UK');
my $day_stone = day_stone($birth_year, $birth_month, $birth_day);
my $sign_stone = sign_stone($sign_name);
print "Birthday: $birthday\n";
print "Birth stone: $month_stone\n";
print "Birth flower (US): $month_flower_US\n";
print "Birth flower (UK): $month_flower_UK\n";
print "Birthday stone: $day_stone\n";
print "Sign stone: $sign_stone\n" if $sign_stone;
}
__DATA__
January |garnet |carnation or snowdrop |carnation
February |amethyst |primrose |violet or iris
March |aquamarine|daffodil |daffodil
April |diamond |sweat pea |sweat pea or daisy
May |emerald |hawthorne or lily of the valley|lily of the valley
June |pearl |rose or honeysuckle |rose
July |ruby |water lily or delphinium |larkspur
August |peridot |poppy or gladiolus |gladiolus
September|sapphire |morning glory or aster |aster or forget-me-not
October |opal |calendula or marigold |marigold
November |topaz |chrysanthemum or peony |chrysanthemum
December |turquoise |holly or Narcissus |pionsetta
Sunday |topaz or diamond
Monday |pearl or crystal
Tuesday |ruby or emerald
Wednesday|amethyst or lodestone
Thursday |sapphire or carnelian
Friday |emerald or cat's eye
Saturday |turquiose or diamond
Capricorn |December |22|January |20|ruby
Aquarius |January |21|February |19|garnet
Pisces |February |20|March |20|amethyst
Aries |March |21|April |20|bloodstone
Taurus |April |21|May |21|sapphire
Gemini |May |22|June |21|agate
Cancer |June |22|July |22|emerald
Leo |July |23|August |22|onyx
Virgo |August |23|September|23|carnelian
Libra |September|24|October |23|chrysolite
Scorpio |October |24|November |22|beryl
Sagittarius|November |23|December |21|topaz