package DateTime::Format::Natural::Base; use strict; use warnings; use boolean qw(true false); use Date::Calc qw(Add_Delta_Days Decode_Day_of_Week Nth_Weekday_of_Month_Year check_date check_time); our $VERSION = '1.15'; use constant MORNING => '08'; use constant AFTERNOON => '14'; use constant EVENING => '20'; sub _ago_seconds { my $self = shift; $self->_add_trace; $self->_subtract(second => shift); $self->_set_modified(3); } sub _ago_minutes { my $self = shift; $self->_add_trace; $self->_subtract(minute => shift); $self->_set_modified(3); } sub _ago_hours { my $self = shift; $self->_add_trace; $self->_subtract(hour => shift); $self->_set_modified(3); } sub _ago_days { my $self = shift; $self->_add_trace; $self->_subtract(day => shift); $self->_set_modified(3); } sub _ago_weeks { my $self = shift; $self->_add_trace; $self->_subtract(week => shift); $self->_set_modified(3); } sub _ago_months { my $self = shift; $self->_add_trace; $self->_subtract(month => shift); $self->_set_modified(3); } sub _ago_years { my $self = shift; $self->_add_trace; $self->_subtract(year => shift); $self->_set_modified(3); } sub _now_minutes_before { my $self = shift; $self->_add_trace; $self->_subtract(minute => shift); $self->_set_modified(4); } sub _now_minutes_from { my $self = shift; $self->_add_trace; $self->_add(minute => shift); $self->_set_modified(4); } sub _now_hours_before { my $self = shift; $self->_add_trace; $self->_subtract(hour => shift); $self->_set_modified(4); } sub _now_hours_from { my $self = shift; $self->_add_trace; $self->_add(hour => shift); $self->_set_modified(4); } sub _now_days_before { my $self = shift; $self->_add_trace; $self->_subtract(day => shift); $self->_set_modified(4); } sub _now_days_from { my $self = shift; $self->_add_trace; $self->_add(day => shift); $self->_set_modified(4); } sub _now_weeks_before { my $self = shift; $self->_add_trace; $self->_subtract(day => (7 * shift)); $self->_set_modified(4); } sub _now_weeks_from { my $self = shift; $self->_add_trace; $self->_add(day => (7 * shift)); $self->_set_modified(4); } sub _now_months_before { my $self = shift; $self->_add_trace; $self->_subtract(month => shift); $self->_set_modified(4); } sub _now_months_from { my $self = shift; $self->_add_trace; $self->_add(month => shift); $self->_set_modified(4); } sub _now_years_before { my $self = shift; $self->_add_trace; $self->_subtract(year => shift); $self->_set_modified(4); } sub _now_years_from { my $self = shift; $self->_add_trace; $self->_add(year => shift); $self->_set_modified(4); } sub _daytime_in_the_morning { my $self = shift; $self->_add_trace; my ($hour) = @_; if ($self->_valid_time(hour => $hour)) { $self->_set(hour => $hour); $self->_set(minute => 0); $self->_set(second => 0); } $self->_set_modified(4); } sub _daytime_in_the_afternoon { my $self = shift; $self->_add_trace; my ($hour) = @_; if ($self->_valid_time(hour => 12 + $hour)) { $self->_set(hour => 12 + $hour); $self->_set(minute => 0); $self->_set(second => 0); } $self->_set_modified(4); } sub _daytime_in_the_evening { my $self = shift; $self->_add_trace; my ($hour) = @_; if ($self->_valid_time(hour => 12 + $hour)) { $self->_set(hour => 12 + $hour); $self->_set(minute => 0); $self->_set(second => 0); } $self->_set_modified(4); } sub _daytime_morning { my $self = shift; $self->_add_trace; my $hour = $self->{Opts}{daytime}{morning} ? $self->{Opts}{daytime}{morning} : MORNING; if ($self->_valid_time(hour => $hour)) { $self->_set(hour => $hour); $self->_set(minute => 0); $self->_set(second => 0); } $self->_set_modified(1); } sub _daytime_noon { my $self = shift; $self->_add_trace; $self->_set(hour => 12); $self->_set(minute => 0); $self->_set(second => 0); $self->_set_modified(1); } sub _daytime_afternoon { my $self = shift; $self->_add_trace; my $hour = $self->{Opts}{daytime}{afternoon} ? $self->{Opts}{daytime}{afternoon} : AFTERNOON; if ($self->_valid_time(hour => $hour)) { $self->_set(hour => $hour); $self->_set(minute => 0); $self->_set(second => 0); } $self->_set_modified(1); } sub _daytime_evening { my $self = shift; $self->_add_trace; my $hour = $self->{Opts}{daytime}{evening} ? $self->{Opts}{daytime}{evening} : EVENING; if ($self->_valid_time(hour => $hour)) { $self->_set(hour => $hour); $self->_set(minute => 0); $self->_set(second => 0); } $self->_set_modified(1); } sub _daytime_midnight { my $self = shift; $self->_add_trace; $self->_set(hour => 0); $self->_set(minute => 0); $self->_set(second => 0); $self->_set_modified(2); } sub _hourtime_before_noon { my $self = shift; $self->_add_trace; $self->_set(hour => 12); $self->_set(minute => 0); $self->_subtract(hour => shift); $self->_set_modified(4); } sub _hourtime_after_noon { my $self = shift; $self->_add_trace; $self->_set(hour => 12); $self->_set(minute => 0); $self->_add(hour => shift); $self->_set_modified(4); } sub _hourtime_before_midnight { my $self = shift; $self->_add_trace; $self->_set(hour => 0); $self->_set(minute => 0); $self->_subtract(hour => shift); $self->_set_modified(4); } sub _hourtime_after_midnight { my $self = shift; $self->_add_trace; $self->_set(hour => 0); $self->_set(minute => 0); $self->_add(hour => shift); $self->_set_modified(4); } sub _day { my $self = shift; $self->_add_trace; my ($day) = @_; if ($self->_valid_date(day => $day)) { $self->_set(day => $day); } $self->_set_modified(1); } sub _day_today { my $self = shift; $self->_add_trace; $self->_set_modified(1); } sub _day_yesterday { my $self = shift; $self->_add_trace; $self->_subtract(day => 1); $self->_set_modified(1); } sub _day_tomorrow { my $self = shift; $self->_add_trace; $self->_add(day => 1); $self->_set_modified(1); } sub _month { my $self = shift; $self->_add_trace; my ($month) = @_; $self->_set(month => $self->_month_num($month)); $self->_set_modified(1); } sub _month_day_after { my $self = shift; $self->_add_trace; my ($month, $day) = @_; $self->_set(month => $self->_month_num($month)); if ($self->_valid_date(day => $day)) { $self->_set(day => $day); } $self->_set_modified(2); } sub _month_day_before { my $self = shift; $self->_add_trace; my ($day, $month) = @_; $self->_set(month => $self->_month_num($month)); if ($self->_valid_date(day => $day)) { $self->_set(day => $day); } $self->_set_modified(2); } sub _year { my $self = shift; $self->_add_trace; my ($year) = @_; if ($self->_valid_date(year => $year)) { $self->_set(year => $year); } $self->_set_modified(1); } sub _weekday { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_day_name(\$day); my $days_diff; # Set current weekday by adding the day difference if ($self->{data}->{weekdays}->{$day} > $self->{datetime}->wday) { $days_diff = $self->{data}->{weekdays}->{$day} - $self->{datetime}->wday; $self->_add(day => $days_diff); } # Set current weekday by subtracting the difference else { $days_diff = $self->{datetime}->wday - $self->{data}->{weekdays}->{$day}; $self->_subtract(day => $days_diff); } $self->_set_modified(1); } sub _last_day { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_day_name(\$day); my $days_diff = $self->{datetime}->wday + (7 - $self->{data}->{weekdays}->{$day}); $self->_subtract(day => $days_diff); $self->_set_modified(2); } sub _last_week_day { my $self = shift; $self->_add_trace; my $day = ucfirst lc(shift); my $days_diff = $self->{datetime}->wday + (7 - $self->{data}->{weekdays}->{$day}); $self->_subtract(day => $days_diff); $self->_set_modified(3); } sub _day_last_week { my $self = shift; $self->_add_trace; my $day = ucfirst lc(shift); my $days_diff = $self->{datetime}->wday + (7 - $self->{data}->{weekdays}->{$day}); $self->_subtract(day => $days_diff); $self->_set_modified(3); } sub _count_day_last_week { my $self = shift; $self->_add_trace; my ($day) = @_; my $days_diff = (7 + $self->{datetime}->wday); $self->_subtract(day => $days_diff); $self->_add(day => $day); $self->_set_modified(4); } sub _last_week { my $self = shift; $self->_add_trace; $self->_subtract(day => 7); $self->_set_modified(2); } sub _last_month { my $self = shift; $self->_add_trace; my ($month) = @_; $self->_subtract(year => 1); $self->_set(month => $self->_month_num($month)); $self->_set_modified(4); } sub _last_month_literal { my $self = shift; $self->_add_trace; $self->_subtract(month => 1); $self->_set_modified(2); } sub _count_day_last_month { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_subtract(month => 1); $self->_set(day => $day); $self->_set_modified(4); } sub _last_year { my $self = shift; $self->_add_trace; $self->_subtract(year => 1); $self->_set_modified(2); } sub _next_weekday { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_day_name(\$day); my $days_diff = (7 - $self->{datetime}->wday + Decode_Day_of_Week($day)); $self->_add(day => $days_diff); $self->_set_modified(2); } sub _weekday_next_week { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_day_name(\$day); my $days_diff = (7 - $self->{datetime}->wday + Decode_Day_of_Week($day)); $self->_add(day => $days_diff); $self->_set_modified(3); } sub _next_month { my $self = shift; $self->_add_trace; my ($month) = @_; $self->_add(year => 1); $self->_set(month => $self->_month_num($month)); $self->_set_modified(2); } sub _next_month_literal { my $self = shift; $self->_add_trace; $self->_add(month => 1); $self->_set_modified(2); } sub _count_day_next_month { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_add(month => 1); $self->_set(day => $day); $self->_set_modified(4); } sub _next_year { my $self = shift; $self->_add_trace; $self->_add(year => 1); $self->_set_modified(2); } sub _count_month_next_year { my $self = shift; $self->_add_trace; my ($month) = @_; $self->_add(year => 1); $self->_set(month => $month); $self->_set_modified(4); } sub _in_count_minutes { my $self = shift; $self->_add_trace; my ($minute) = @_; $self->_add(minute => $minute); $self->_set_modified(3); } sub _in_count_hours { my $self = shift; $self->_add_trace; my ($hour) = @_; $self->_add(hour => $hour); $self->_set_modified(3); } sub _in_count_days { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_add(day => $day); $self->_set_modified(3); } sub _this_second { my $self = shift; $self->_add_trace; $self->_set_modified(2); } sub _this_weekday { my $self = shift; $self->_add_trace; my ($day) = @_; $self->_day_name(\$day); my $days_diff = $self->{data}->{weekdays}->{$day} - $self->{datetime}->wday; $self->_add(day => $days_diff); $self->_set_modified(2); } sub _weekday_this_week { my $self = shift; $self->_add_trace; my ($day) = @_; $day = ucfirst lc $day; my $days_diff = Decode_Day_of_Week($day) - $self->{datetime}->wday; $self->_add(day => $days_diff); $self->_set_modified(3); } sub _this_month { my $self = shift; $self->_add_trace; $self->_set_modified(2); } sub _count_weekday_this_month { my $self = shift; my ($count, $day, $month) = @_; $self->_add_trace; $self->_day_name(\$day); $self->_month_name(\$month); my $year; ($year, $month, $day) = Nth_Weekday_of_Month_Year($self->{datetime}->year, $self->{data}->{months}->{$month}, $self->{data}->{weekdays}->{$day}, $count); $self->_set(year => $year); $self->_set(month => $month); $self->_set(day => $day); $self->_set_modified(4); } sub _daytime_variant_before_yesterday { my $self = shift; $self->_add_trace; $self->_subtract(day => 2); $self->_set(hour => (24 - shift)); $self->_set_modified(4); } sub _daytime_variant_after_yesterday { my $self = shift; $self->_add_trace; $self->_subtract(day => 1); $self->_set(hour => (0 + shift)); $self->_set_modified(4); } sub _daytime_variant_before_tomorrow { my $self = shift; $self->_add_trace; $self->_set(hour => (24 - shift)); $self->_set_modified(4); } sub _daytime_variant_after_tomorrow { my $self = shift; $self->_add_trace; $self->_add(day => 1); $self->_set(hour => (0 + shift)); $self->_set_modified(4); } sub _at_am { my $self = shift; $self->_add_trace; my ($time) = @_; if ($time =~ /:/) { my ($hour, $minute) = split /:/, $time; if ($self->_valid_time(hour => $hour, minute => $minute)) { $self->_set(hour => $hour); $self->_set(minute => $minute); } } else { if ($self->_valid_time(hour => $time)) { $self->_set(hour => $time); $self->_set(minute => 0); } } $self->_set_modified(2); } sub _at_pm { my $self = shift; $self->_add_trace; my ($time) = @_; if ($time =~ /:/) { my ($hour, $minute) = split /:/, $time; if ($self->_valid_time(hour => 12 + $hour, minute => $minute)) { $self->_set(hour => 12 + $hour); $self->_set(minute => $minute); } } else { if ($self->_valid_time(hour => 12 + $time)) { $self->_set(hour => 12 + $time); $self->_set(minute => 0); } } $self->_set_modified(2); } sub _time { my $self = shift; $self->_add_trace; my ($time) = @_; if ($time =~ /:/) { my ($hour, $minute) = split /:/, $time; if ($self->_valid_time(hour => $hour, minute => $minute)) { $self->_set(hour => $hour); $self->_set(minute => $minute); } } else { if ($self->_valid_time(hour => $time)) { $self->_set(hour => $time); $self->_set(minute => 0); } } $self->_set_modified(1); } sub _time_full { my $self = shift; $self->_add_trace; my ($time) = @_; my ($hour, $minute, $second) = split /:/, $time; if ($self->_valid_time(hour => $hour, minute => $minute, second => $second)) { $self->_set(hour => $hour); $self->_set(minute => $minute); $self->_set(second => $second); } $self->_set_modified(1); } sub _today { my $self = shift; $self->_add_trace; $self->_set_modified(1); } sub _count_yearday { my $self = shift; $self->_add_trace; my ($day) = @_; my ($year, $month); ($year, $month, $day) = Add_Delta_Days($self->{datetime}->year, 1, 1, $day - 1); $self->_set(day => $day); $self->{datetime}->set_month($month); $self->{datetime}->set_year($year); $self->_set_modified(2); } sub _count_weekday { my $self = shift; $self->_add_trace; my ($count, $weekday) = @_; $weekday = ucfirst lc $weekday; my ($year, $month, $day) = Nth_Weekday_of_Month_Year($self->{datetime}->year, $self->{datetime}->month, $self->{data}->{weekdays}->{$weekday}, $count); if ($self->_valid_date(day => $day, month => $month, year => $year)) { $self->_set(day => $day); $self->_set(month => $month); $self->{datetime}->set_year($year); } $self->_set_modified(2); } sub _day_month_year { my $self = shift; $self->_add_trace; my ($day, $month, $year) = @_; $self->_month_name(\$month); $self->{datetime}->set( year => $year, month => $self->_month_num($month), day => $day, ); $self->_set_modified(3); } sub _day_name { my $self = shift; my ($day) = @_; $$day = ucfirst lc $$day; if (length $$day == 3) { $$day = $self->{data}->{weekdays_abbrev}->{$$day}; } } sub _month_name { my $self = shift; my ($month) = @_; $$month = ucfirst lc $$month; if (length $$month == 3) { $$month = $self->{data}->{months_abbrev}->{$$month}; } } sub _month_num { my $self = shift; my ($month) = @_; $month = ucfirst lc $month; if (length $month == 3) { $month = $self->{data}->{months_abbrev}->{$month}; } return $self->{data}->{months}->{$month}; } sub _add { my ($self, $unit, $value) = @_; $self->{modified}{$unit}++; $unit .= 's' unless $unit =~ /s$/; $self->{datetime}->add($unit => $value); } sub _subtract { my ($self, $unit, $value) = @_; $self->{modified}{$unit}++; $unit .= 's' unless $unit =~ /s$/; $self->{datetime}->subtract($unit => $value); } sub _set { my ($self, $unit, $value) = @_; $self->{modified}{$unit}++; my $setter = 'set_' . $unit; $self->{datetime}->$setter($value); } sub _valid_date { my ($self, $type, $value) = @_; my %set = map { $_ => $self->{datetime}->$_ } qw(year month day); $set{$type} = $value; if (check_date($set{year}, $set{month}, $set{day})) { return true; } else { $self->_set_failure; $self->_set_error("('$value' is not a valid $type)"); return false; } } sub _valid_time { my ($self, $type, $value) = @_; my %set = map { $_ => $self->{datetime}->$_ } qw(hour min sec); $set{$type} = $value; if (check_time($set{hour}, $set{min}, $set{sec})) { return true; } else { $self->_set_failure; $self->_set_error("('$value' is not a valid $type)"); return false; } } 1; __END__ =head1 NAME DateTime::Format::Natural::Base - Base class for DateTime::Format::Natural =head1 SYNOPSIS Please see the DateTime::Format::Natural documentation. =head1 DESCRIPTION The C class defines the core functionality of C. =head1 SEE ALSO L =head1 AUTHOR Steven Schubiger =head1 LICENSE This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. See L =cut