use warnings;
use Data::Dumper;
use Time::Local;
+use PVE::JSONSchema;
+use PVE::Tools qw(trim);
# Note: This class implements a parser/utils for systemd like calender exents
# Date specification is currently not implemented
sat => 6,
};
+PVE::JSONSchema::register_format('pve-calendar-event', \&pve_verify_calendar_event);
+sub pve_verify_calendar_event {
+ my ($text, $noerr) = @_;
+
+ eval { parse_calendar_event($text); };
+ if (my $err = $@) {
+ return undef if $noerr;
+ die "invalid calendar event '$text' - $err\n";
+ }
+ return $text;
+}
+
# The parser.
# returns a $calspec hash which can be passed to compute_next_event()
sub parse_calendar_event {
my ($event) = @_;
+ $event = trim($event);
+
+ if ($event eq '') {
+ die "unable to parse calendar event - event is empty\n";
+ }
+
my $parse_single_timespec = sub {
my ($p, $max, $matchall_ref, $res_hash) = @_;
$$matchall_ref = 1;
} else {
$start = int($start);
+ die "value '$start' out of range\n" if $start >= $max;
$res_hash->{$start} = 1;
}
}
if ($time_spec =~ m/^($chars+):($chars+)$/) {
my ($p1, $p2) = ($1, $2);
- $parse_single_timespec->($p1, 24, \$matchall_hours, $hours_hash);
- $parse_single_timespec->($p2, 60, \$matchall_minutes, $minutes_hash);
+ foreach my $p (split(',', $p1)) {
+ $parse_single_timespec->($p, 24, \$matchall_hours, $hours_hash);
+ }
+ foreach my $p (split(',', $p2)) {
+ $parse_single_timespec->($p, 60, \$matchall_minutes, $minutes_hash);
+ }
} elsif ($time_spec =~ m/^($chars)+$/) { # minutes only
$matchall_hours = 1;
foreach my $p (split(',', $time_spec)) {
if ($matchall_hours) {
$h = '*';
} else {
- $h = [ sort keys %$hours_hash ];
+ $h = [ sort { $a <=> $b } keys %$hours_hash ];
}
if ($matchall_minutes) {
$m = '*';
} else {
- $m = [ sort keys %$minutes_hash ];
+ $m = [ sort { $a <=> $b } keys %$minutes_hash ];
}
return { h => $h, m => $m, dow => [ sort keys %$dow_hash ]};
if ($utc) {
(undef, $min, $hour, $mday, $mon, $year, $wday) = gmtime($last);
+ # gmtime and timegm interpret two-digit years differently
+ $year += 1900;
$startofday = timegm(0, 0, 0, $mday, $mon, $year);
} else {
(undef, $min, $hour, $mday, $mon, $year, $wday) = localtime($last);
+ # localtime and timelocal interpret two-digit years differently
+ $year += 1900;
$startofday = timelocal(0, 0, 0, $mday, $mon, $year);
}