use v6; use WorkdayCalendar; use TimeOfDay; class Schedule { subset DaysInWeek of Str where ; subset WeeksInMonth of Int where 1..5; subset DaysInMonth of Int where 1..31; subset MonthsInYear of Int where ; subset TimeOut of Int where $_ > 0; has DateTime $.present is rw = DateTime.now; has Str $.id; has TimeOfDay @.time is rw; has DaysInWeek @.weekdays is rw; has WeeksInMonth @.ordinal is rw; #--- Ordinal weekday modifier: 1st monday of the month, 5th friday of the month (last) has DaysInMonth @.monthdays is rw; has MonthsInYear @.months is rw; has TimeOut $.timeout is rw; has WorkdayCalendar $.calendar; has DateTime $!next-instants is rw; has Bool $.recover-lost-events = False; has Bool $.advance-lost-events = False; #method future-events(DateTime $from = now, DateTime $until = $from + (60*60*24)*(30*3) ) { method future-events { #--- If the months are not populated, means "every month" @.months = if @.months.elems == 0; my Str @whole_schedule = ( ( ( ('MNTH=' X~ (@.months.elems == 0) ?? '' !! @.months) X~ (';ORDN=' X~ (@.ordinal.elems == 0) ?? '' !! @.ordinal) ) X~ (';MDAY=' X~ (@.monthdays.elems == 0) ?? '' !! @.monthdays) ) X~ (';WDAY=' X~ (@.weekdays.elems == 0) ?? '' !! @.weekdays) ) X~ (';TIME=' X~ (@.time.elems == 0) ?? '' !! @.time) #--- hlighter? ; my %event_spec; my Int $index = 0; for @whole_schedule -> $event { my @event_data = split /';'/, $event; for @event_data -> $data { my (Str $type, Str $value) = split '=', $data; if $value ne '' { my %ev; %ev{$type} = $value; %event_spec{$index} = %ev; say $index ~ %ev.perl ~ "===>" ~ %event_spec.perl; } # This is a workaround until (%h = x) is implemented on rakudo } $index++; } say %event_spec.perl; exit; #TODO: Clean %event_spec of invalid dates for %event_spec.keys -> $index { say ">>event " ~ $index; my %e = %event_spec{$index}; say %e.perl; #--- Validating event specification try { if defined %e{'ORDN'} && defined %e{'MDAY'} { warn "ERROR: Can't specify an ordinal weekday modifier and a week-number at the same time."; } if defined %e{'WDAY'} && defined %e{'MDAY'} { warn "ERROR: Can't specify a monthday and a weekday at the same time."; } if !defined %e{'TIME'} { warn "ERROR: A time specification is needed"; } CATCH { note "ERROR: event specification flawed"; next; } } #--- Combos if defined %e{'ORDN'} && defined %e{'WDAY'} { #--- Find the Nth corresponding Weekday of the month my $month_number = self.__month-name-to-number( %e{'MHTN'} ); say ">>> $month_number"; my $start = Date.new( $.present.year ~ '-' ~ $month_number.fmt('%02d') ~ '-01' #'T ~ $.present.hour ~ ':' ~ $.present.minute ~ ':' ~ $.present.second ~ 'Z' ); my $weekdays_found = 0; my Date $current_day = $start; say "dow $current_day.day-of-week"; for (1..$start.days-in-month) -> $day_in_month { my $current_day = $current_day.succ; my %wd = enum ; $weekdays_found++ if $current_day.day-of-week == %e{'WDAY'}; last if $weekdays_found == %e{'ORDN'}; } #--- $current_day is the day we are looking for now. } my ($hour, $minute, $second) = (0,0,0); ($hour, $minute, $second) = split ':', %event_spec{$index}{'TIME'}; my $event = DateTime.new( hour=>$hour.Int, minute=>$minute.Int, second=>$second.Int ); } return %event_spec; } method next-instant(DateTime $from = now) { my Workdate $start_date .= new($from, $.calendar); my TimeOfDay $start_time = TimeOfDay.new( hour => $from.hour, minute => $from.minute, second => $from.second ) } method when-next(DateTime $from = now) { } method when-previous(DateTime $from = now) { } method __month-name-to-number($month_name) { my $month_number = 0; for { $month_number++; last if $_ eq $month_name; } return $month_number; } }