2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-10 09:16:53 +00:00

Cron.pm: wip

git-svn-id: https://svn.fhem.de/fhem/trunk@27875 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
herrmannj 2023-08-22 22:38:32 +00:00
parent 9f1b77ab2b
commit 560d36649b

View File

@ -116,7 +116,7 @@ sub _next {
} else {
# new day, therefore start with from_time = 000000 (inclusive: >=)
# that also requires a pointer reset, done above
($next_time, $day_changed) = $next_time = $self->_next_time(000000, 1);
($next_time, $day_changed) = $self->_next_time('000000', 1);
$self->{working_time} = $next_time;
}
@ -439,16 +439,20 @@ sub _next_calendar_date {
# the ptr points to the correspondig list entry
$self->{month_ptr} //= sub {
$self->log(5, 'initialize month pointer') if $ENV{EXTENDED_DEBUG};
my $t = shift;
my $i = 0;
return 0 if ($self->{list_of_months}->[$i] >= $_[0]);
while ($self->{list_of_months}->[$i] < $_[0] and $i < $#{$self->{list_of_months}}) {$i++}
return 0 if ($self->{list_of_months}->[$i] >= $t);
while ($self->{list_of_months}->[$i] < $t and $i < $#{$self->{list_of_months}}) {$i++}
return $i}->($month);
$self->{mday_ptr} //= sub {
$self->log(5, 'initialize mdy pointer') if $ENV{EXTENDED_DEBUG};
my $t = shift;
my $v = shift;
my $i = 0;
return 0 if ($self->{list_of_mdays}->[$i] >= $_[0]);
while ($self->{list_of_mdays}->[$i] < $_[0] and $i < $#{$self->{list_of_mdays}}) {$i++}
return $i}->($mday);
return 0 if ($self->{list_of_months}->[$self->{month_ptr}] != $v);
return 0 if ($self->{list_of_mdays}->[$i] >= $t);
while ($self->{list_of_mdays}->[$i] < $t and $i < $#{$self->{list_of_mdays}}) {$i++}
return $i}->($mday, $month);
$self->log(5, 'pointer set: month %d(%d) mday %d(%d)', $self->{month_ptr}, $self->{list_of_months}->[$self->{month_ptr}], $self->{mday_ptr}, $self->{list_of_mdays}->[$self->{mday_ptr}]) if $ENV{EXTENDED_DEBUG};
@ -493,9 +497,7 @@ sub _next_calendar_date {
return $found;
}
# Input is the date from which the next date is to be determined
# input array (year, month, mday) 'from'
# return is greater or equal to the input date
sub _next_weekday_date {
my $self = shift;
my $from_date = shift; # date
@ -507,45 +509,61 @@ sub _next_weekday_date {
$inclusive?'at or after (inclusive)':'after (exclusive)',
$year, $month, $mday) if $ENV{EXTENDED_DEBUG};
# test-candidate year
my $y = $year;
# test-candidate month
# initialize cache if not done already
if (not defined($self->{month_ptr_wday})) {
$self->{month_ptr_wday} = first { print "test $#{$self->{list_of_months}} $_ \n"; $self->{list_of_months}->[$_] >= $month } 0 .. $#{$self->{list_of_months}};
$self->{month_ptr_wday} //= 0; # case month < first entry
}
my $m = $self->{list_of_months}->[$self->{month_ptr_wday}];
$y++ if $m < $month;
# initialize ptr or use cached values
# the ptr points to the correspondig list entry
$self->{weekday_month_ptr} //= sub {
$self->log(5, 'initialize weekday month pointer') if $ENV{EXTENDED_DEBUG};
my $t = shift;
my $i = 0;
return 0 if ($self->{list_of_months}->[$i] >= $t);
while ($self->{list_of_months}->[$i] < $t and $i < $#{$self->{list_of_months}}) {$i++}
return $i}->($month);
$self->log(5, 'pointer set: month %d(%d)', $self->{weekday_month_ptr}, $self->{list_of_months}->[$self->{weekday_month_ptr}]) if $ENV{EXTENDED_DEBUG};
# # test-candidate month
# # initialize cache if not done already
# if (not defined($self->{month_ptr_wday})) {
# $self->{month_ptr_wday} = first { print "test $#{$self->{list_of_months}} $_ \n"; $self->{list_of_months}->[$_] >= $month } 0 .. $#{$self->{list_of_months}};
# $self->{month_ptr_wday} //= 0; # case month < first entry
# }
my $found = undef;
my $year_next = $year;
while (not defined($found)) {
my ($y, $m) = ($year_next, $self->{list_of_months}->[$self->{weekday_month_ptr}]);
my $d = ($m != $month) ? 1 : $mday;
printf('first weekday candidate: %4d%02d%02d ptr: %d %s', $y, $m, $d, $self->{month_ptr_wday}, "\n");
until (($self->{next_weekday_date} // 0) >= sprintf('%4d%02d%02d', $year, $month, $mday)) {
my $candidate = sprintf('%04d%02d%02d', $y, $m, $d);
$self->log(5, 'test candidate %04d-%02d-%02d', $y, $m, $d) if $ENV{EXTENDED_DEBUG};
# weekday of candidate
my $wday = $self->get_weekday($y, $m, $d);
# first following upcoming wday from the 'or' list. if the first possible wday < current wday, add one week (7 days)
my $first = (first {$_ >= $wday} @{ $self->{list_of_or_wdays} }) // $self->{list_of_or_wdays}->[0] + 7;
my $first;
if ($inclusive) {
$first = (first {$_ >= $wday} @{ $self->{list_of_or_wdays} }) // $self->{list_of_or_wdays}->[0] + 7;
} else {
$first = (first {$_ > $wday} @{ $self->{list_of_or_wdays} }) // $self->{list_of_or_wdays}->[0] + 7;
}
# how many days in the future
my $day_diff = $first - $wday;
my $next_wday_in_month = $d + $day_diff;
printf('candidate %4d%02d%02d is weekday %d - next from \'or_list\' is %d - resulting in day %d %s', $y, $m, $d, $wday, $first, $next_wday_in_month, "\n");
# if $next_wday_in_month > days in month, advance ptr to next month
$self->log(5, 'candidate %4d-%02d-%02d is weekday %d - next from \'or_list\' is %d - resulting in mday %d', $y, $m, $d, $wday, $first, $next_wday_in_month) if $ENV{EXTENDED_DEBUG};
if ($self->is_valid_date($y, $m, $next_wday_in_month)) {
printf('candidate %4d%02d%02d on weekday %d is a valid date %s', $y, $m, $next_wday_in_month, $first % 6, "\n");
$self->{next_weekday_date} = sprintf('%4d%02d%02d', $y, $m, $next_wday_in_month);
$self->log(5, 'found candidate %4d-%02d-%02d', $y, $m, $next_wday_in_month);
$found = sprintf('%4d%02d%02d', $y, $m, $next_wday_in_month);
# last;
} else {
# first day of next available month
$self->{month_ptr_wday}++;
if ($self->{month_ptr_wday} > $#{$self->{list_of_months}}) {
$self->{month_ptr_wday} = 0;
$self->{weekday_month_ptr}++;
if ($self->{weekday_month_ptr} > $#{$self->{list_of_months}}) {
$self->{weekday_month_ptr} = 0;
$y++;
}
$m = $self->{list_of_months}->[$self->{month_ptr_wday}];
$m = $self->{list_of_months}->[$self->{weekday_month_ptr}];
$d = 1;
}
}
return $found;
}
sub get_weekday {
@ -567,6 +585,25 @@ sub get_weekday {
return $weekday_num;
}
sub is_valid_date {
my $self = shift;
my ($year, $month, $day) = @_;
# Checking the validity of the year, month and day
return 0 if $year < 0 || $month < 1 || $month > 12 || $day < 1 || $day > 31;
# List of days per month (without leap years)
my @days_in_month = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
# Leap year check
if ($month == 2 && (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0)) {
$days_in_month[2] = 29;
}
# Check if the day exists in the given month
return $day <= $days_in_month[$month];
}
# $from_time: time from which the next time is to be determined as hhmmss
# $inclusive: TRUE: include from time (>=), FALSE: exclude $from_time (>)
@ -575,27 +612,30 @@ sub _next_time {
my $from_time = shift;
my $inclusive = shift;
# my ($hour, $minute, $second) = ($from_time =~ m/(\d{2})(\d{2})(\d{2})/);
my ($hour, $minute, $second) = ($from_time =~ m/(\d{2})(\d{2})(\d{2})/);
$self->log(5, 'search next time %s %02d:%02d:%02d',
$inclusive?'at or after (inclusive)':'after (exclusive)',
($from_time =~ m/(\d{2})(\d{2})(\d{2})/)) if $ENV{EXTENDED_DEBUG};
my ($hour, $minute, $second) = ($from_time =~ m/(\d{2})(\d{2})(\d{2})/);
$hour, $minute, $second) if $ENV{EXTENDED_DEBUG};
# initialize ptr or use cached values
# the ptr points to the correspondig list entry
$self->{hour_ptr} //= sub {
$self->log(5, 'initialize hour pointer') if $ENV{EXTENDED_DEBUG};
my $t = shift;
my $i = 0;
return 0 if ($self->{list_of_hours}->[$i] >= $_[0]);
while ($self->{list_of_hours}->[$i] < $_[0] and $i < $#{$self->{list_of_hours}}) {$i++}
return 0 if ($self->{list_of_hours}->[$i] >= $t);
while ($self->{list_of_hours}->[$i] < $t and $i < $#{$self->{list_of_hours}}) {$i++}
return $i}->($hour);
$self->{minute_ptr} //= sub {
$self->log(5, 'initialize minute pointer') if $ENV{EXTENDED_DEBUG};
my $t = shift;
my $v = shift;
my $i = 0;
return 0 if ($self->{list_of_minutes}->[$i] >= $_[0]);
while ($self->{list_of_minutes}->[$i] < $_[0] and $i < $#{$self->{list_of_minutes}}) {$i++}
return $i}->($minute);
return 0 if ($self->{list_of_hours}->[$self->{hour_ptr}] != $v);
return 0 if ($self->{list_of_minutes}->[$i] >= $t);
while ($self->{list_of_minutes}->[$i] < $t and $i < $#{$self->{list_of_minutes}}) {$i++}
return $i}->($minute, $hour);
$self->log(5, 'pointer set: hour %d(%d) minute %d(%d)', $self->{hour_ptr}, $self->{list_of_hours}->[$self->{hour_ptr}], $self->{minute_ptr}, $self->{list_of_minutes}->[$self->{minute_ptr}]) if $ENV{EXTENDED_DEBUG};
@ -700,24 +740,4 @@ sub _next_special_date {
} until (scalar @list)
}
sub is_valid_date {
my $self = shift;
my ($year, $month, $day) = @_;
# Überprüfung der Gültigkeit von Jahr, Monat und Tag
return 0 if $year < 0 || $month < 1 || $month > 12 || $day < 1 || $day > 31;
# Liste der Tage pro Monat (ohne Schaltjahre)
my @days_in_month = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
# Schaltjahr-Überprüfung
if ($month == 2 && (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0)) {
$days_in_month[2] = 29;
}
# Überprüfung, ob der Tag im gegebenen Monat existiert
return $day <= $days_in_month[$month];
}
1;