views:

47

answers:

4

So I have list of events that are sort of like alarms. They're defined by their start and end time (in hours and minutes), a range of days (ie 1-3 which is sunday through wed.), and a range of months (ie 1-3, january through march). The format of that data is largely unchangeable. I need to, not necessarily sort the list, but I need to find the next upcoming event based on the current time. There's just so many different ways to do this and so many different corner cases. This is my pseudo code:



now = time()
diff = []
# Start difference between now and start times
for s in schedule #assuming appending to diff
    diff.minutes = s.minutes - time.minutes #
    diff.hours = s.hours - time.hours
    diff.days = s.days - time.days
    diff.months = s.months - time.months

for d in diff
    if d < 0
        d = period + d 
        # period is the maximum period of the attribute. ie minutes is 60, hours is 24

# repeat for event end times


So now I have a list of tuples of differences in hours, minutes, days, and weeks. This tuple already takes into account if it's passed the start time, but before the end time. So let's say it's in August and the start month of the event is July and the end month is September, so diff.month == 0.

Now this specific corner case is giving me trouble:

Let's say a schedule runs from 0 to 23:59 thursdays in august. And it's Friday the 27th. Running my algorithm, the difference in months would be 0 when in reality it won't run again until next august, so it should be 12. And I'm stuck. The month is the only problem I think because the month is the only attribute that directly depends on what the date of the specific month is (versus just the day). Is my algorithm OK and I can just deal with this special case? Or is there something better out there for this?

This is the data I'm working with

    map['start_time']=''
    map['end_time']=''
    map['start_moy']='' 
    map['end_moy']='' 
    map['start_dow']=''      
    map['end_dow']=''

The schedule getAllSchedules method just returns a list to all of the schedules. I can change the schedule class but I'm not sure what difference I can make there. I can't add/change the format of the schedules I'm given

+1  A: 

Convert the items from the schedule into datetime objects. Then you can simply sort them

from datetime import datetime
events = sorted(datetime(s.year, s.month, s.day, s.hour, s.minute) for s in schedule)
gnibbler
The problem is the scheduled event doesn't have an actual date associated with it, just thursdays in august. If I could convert to a datetime that would be nice, but without the actual date, I would still have to solve the problem I currently have
Falmarri
@Falmarri, It will still be best to leverage the datetime module as that will take care of your corner cases. Can you should the code for you schedule class?
gnibbler
I also don't have a year attribute
Falmarri
@Falmarri, perhaps you can substitute `datetime.now().year` if the year doesn't matter. I can't tell for sure unless I see the schedule class
gnibbler
I probably shouldn't post the actual code. Do you mean my schedule class I'm calling above? All it returns is a map of the information I've already given, it's just a Parser class to return a map to each of the events. I'll post the actual fields in my question. If you're talking about the scheduler that will be actually running and asking me for my times, I have no idea how that will be implemented.
Falmarri
+1  A: 

Since your resolution is in minutes, and assuming that you don't have many events, then I'd simply scan all the events every minute.

Filter your events so that you have a new list where the event range match the current month and day.

Then for each of those events declare that they are active or inactive according to whether the current time matches the event's range.

quamrana
I have no control over how often the scheduler runs. All I have to do is give it the next scheduled event when it asks me
Falmarri
+1  A: 

The primary issue seems to be with the fact that you're using the day of the week, instead of explicit days of the month.

While your cited edge case is one example, does this issue not crop up with all events scheduled in any month outside of the current one?

I think the most robust approach here would be to do the work to get your scheduled events into datetime format, then use @gnibbler's suggestion of sorting the datetime objects.

Once you have determined that the last event for the current month has already passed, calculate the distance to the next month the event occurs in (be it + 1 year, or just + 1 month), then construct a datetime object with that information:

first_of_month = datetime.date(calculated_year, calculated_month, 1)

By using the first day of the month, you can then use:

day_of_week = first_of_month.strftime('%w')

To give you what day of the week the first of that month falls on, which you can then use to calculate how many days to add to get to the first, second, third, etc. instance of a given day of the week, for that month. Once you have that day, you can construct a valid datetime object and do whatever comparisons you wish with now().

Andrew
That's more or less what my algorithm above is doing. However, that still misses the corner case of being in a month with no more of a certain day
Falmarri
Edited my solution to solely address the edge cases.
Andrew
A: 

I couldn't figure out how to do it using only datetimes. But I found a module and used this. It's perfect

http://labix.org/python-dateutil

Falmarri