All pastes #2131165 Raw Edit

Someone

public text v1 · immutable
#2131165 ·published 2012-03-22 18:51 UTC
rendered paste body
use v6;

use WorkdayCalendar;
use TimeOfDay;

class Schedule {
    
    subset DaysInWeek   of Str where <Mon Tue Wed Thu Fri Sat Sun>;
    subset WeeksInMonth of Int where 1..5;
    subset DaysInMonth  of Int where 1..31;
    subset MonthsInYear of Int where <Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec>;
    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 = <Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec> 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<a><b> = 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 <Mon Tue Wed Thu Fri Sat Sun>;
                    $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 <Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec> {
            $month_number++;
            last if $_ eq $month_name; 
        }
        return $month_number;
    }
}