Scheduled buses API

Is it possible to fetch the schedule of buses due at a specific stop?
The closest i’ve got is using the /Line/<lineId>/Timetable/<stopId> endpoint which returns the timetable, however that means I need to know what type of day today is, eg. “Mon-Fri Schooldays” to know if the schedule is valid for today. Then I assume there are different schedules for Bank Holidays etc…

Is there no API that just lists today’s schedule?

This is how I decode them.

class DayWordsToBitmap
{
 public static function dayWordsToBitmap($id)
{
    switch ($id) {
        // 1 (for Monday) through 7 (for Sunday)

        case "Monday":
        case "Bank Holidays":
            return pow(2, ViewBusStopTimetables::MONDAY);
        case "Tuesday":
            return pow(2, ViewBusStopTimetables::TUESDAY);
        case "Wednesday":
            return pow(2, ViewBusStopTimetables::WEDNESDAY);
        case "Thursday":

            return pow(2, ViewBusStopTimetables::THURSDAY);
        case "Friday":
        case "School Friday":
        case "Non-School Friday":
            return pow(2, ViewBusStopTimetables::FRIDAY);
        case "Saturday":
            return pow(2, ViewBusStopTimetables::SATURDAY);
        case "Sunday":
            return pow(2, ViewBusStopTimetables::SUNDAY);

        case "Monday to Friday":
        case "Mon-Fri Schooldays":
        case "Summer Monday to Friday Non-Schooldays":
        case "Mon-Fri Non-Schooldays":
        case "Mo-Fr Night/Tu-Sat Morning":
        case "Monday - Friday":

        case "MondayToFriday":

            return pow(2, ViewBusStopTimetables::MONDAY) | pow(2, ViewBusStopTimetables::TUESDAY) | pow(2, ViewBusStopTimetables::WEDNESDAY) | pow(2, ViewBusStopTimetables::THURSDAY) | pow(2, ViewBusStopTimetables::FRIDAY);
        case "Monday to Thursday":
        case "Mo-Th Nights/Tu-Fr Morning":
        case "Mon-Th Schooldays":
        case "Mon-Th Non-Schooldays":

        case "Monday -Thursday Non-Schooldays":

        case "Monday,Tuesday,Wednesday,Thursday":

            return pow(2, ViewBusStopTimetables::MONDAY) | pow(2, ViewBusStopTimetables::TUESDAY) | pow(2, ViewBusStopTimetables::WEDNESDAY) | pow(2, ViewBusStopTimetables::THURSDAY);


        case "Monday,Tuesday,Thursday,Friday":

            return pow(2, ViewBusStopTimetables::MONDAY) | pow(2, ViewBusStopTimetables::TUESDAY) | pow(2, ViewBusStopTimetables::THURSDAY) | pow(2, ViewBusStopTimetables::FRIDAY);


        case "Tuesday, Wednesday & Thursday":
        case "Tuesday,Wednesday,Thursday":
            return pow(2, ViewBusStopTimetables::TUESDAY) | pow(2, ViewBusStopTimetables::WEDNESDAY) | pow(2, ViewBusStopTimetables::THURSDAY);


        case "Sunday Night/Monday Morning":
            return pow(2, ViewBusStopTimetables::MONDAY);
        case "Saturday Night/Sunday Morning":
            return pow(2, ViewBusStopTimetables::SUNDAY);

        case "Friday Night/Saturday Morning":
            return pow(2, ViewBusStopTimetables::SATURDAY);


        case "Tuesday,Wednesday,Thursday,Friday":
            return pow(2, ViewBusStopTimetables::TUESDAY) | pow(2, ViewBusStopTimetables::WEDNESDAY) | pow(2, ViewBusStopTimetables::THURSDAY) | pow(2, ViewBusStopTimetables::FRIDAY);


        case "Monday,Tuesday,Wednesday,Thursday,Sunday":
            return pow(2, ViewBusStopTimetables::MONDAY) | pow(2, ViewBusStopTimetables::TUESDAY) | pow(2, ViewBusStopTimetables::WEDNESDAY) | pow(2, ViewBusStopTimetables::THURSDAY) | pow(2, ViewBusStopTimetables::SUNDAY);


        case "MondayToSunday":

            return pow(2, ViewBusStopTimetables::MONDAY) | pow(2, ViewBusStopTimetables::TUESDAY) | pow(2, ViewBusStopTimetables::WEDNESDAY) | pow(2, ViewBusStopTimetables::THURSDAY) | pow(2, ViewBusStopTimetables::FRIDAY) | pow(2, ViewBusStopTimetables::SATURDAY) | pow(2, ViewBusStopTimetables::SUNDAY);

        case "":
            return 0;

        default:
            die(__FUNCTION__ . " " . $id);
    }
}
}

class ViewBusStopTimetables extends busschedules 
{
const MONDAY = 1;
const TUESDAY = 2;
const WEDNESDAY = 3;
const THURSDAY = 4;
const FRIDAY = 5;
const SATURDAY = 6;
const SUNDAY = 7;
}

Thank you @briantist however this still leaves me with the problem of “What type of day is today?”.

If I want to show a schedule of buses due today, how do I know if today is a school holiday, school term day, bank holiday etc…
Does any API give this information for todays type?

@ddaddy

Bank Holidays are on this feed → https://www.gov.uk/bank-holidays/england-and-wales.ics

School Holidays - see this for a non-answer How to determine if School Holidays in Effect

Thanks again. I shall go and have a read through that.

1 Like

I am coming at this from a quite different angle, namely the published Working Timetables. This may not be the same problem but it seems to have something in common.

There are probably at least 57 varieties of day type visible within these, including lots of “specials”. It is pretty obvious from these that different operators (and perhaps different compilers) use different codes for exactly the same operating days; Christmas week specials might be sMF, sMT, sSa, while what one operator means by sMF (say) may differ from what another operator means. The various Covid specials cropped up in different guises and even now some of the Covid extras are MF and some MFSc.

None of this matters operationally as long as operator and TfL are on the same page for each individual route but it makes it difficult for third parties.

I have heard suggestions that thee is a master record somewhere within TfL that shows exactly which schedule is supposed to operate on each day for each route. If this does exist it would be great to have access to it.

The school holiday situation is particularly complex, I would suggest. Some of the special schedules (that is, with reduced running times)only operate in summer, some also at Easter and some in all school holidays. I’ve heard itn suggested that some operators don’t bother running them at half term, or for part-weeks if the school term starts or finishes midweek.

There is also scope for confusion between specials and Summer. I’ve noticed that the schedule for replacement route UL69 keeps oscillating between SSu (Summer Sndays) and sSu (special Sundays), presumably because somewhere along the line there is a process that is not case sensitive. It’s unfortunate that s and S are noth used as prefixes.

1 Like

@mjcarchive

The fact that someone could go to the whole damn trouble of creating the TransXChange Schema and then fail totally to be able to clearly define what the actual day pattern for a service is when even a child would start with that rather obvious piece of information.

@ddaddy

The code has been used against both the unified API and published Working Timetables.

I’ve implemented 5 other operator API’s and every single one can tell me what buses are due today and when. I shouldn’t have to make my own assumptions on whether a bus is running today because the schools are in or not.

I’m still waiting for the ‘live bus location’ to be implemented so will revisit TFL in 6 months and see if anything has improved.

Thanks for your help.

@briantist
In theory it may be possible to work it out from the XML files in Datastore, as these contain fields for Days of Operation and Days of Non-operation but I’ve never been able to work out how to use them. Presumably Journey Planner can!

@mjcarchive

The code I wrote and posted above was my shot at decoding the XML files in Datastore. I would have been MUCH better if the datastore had used a bitmap to define the days of operation like this say:

  • 10011111 - Monday to Friday plus bank holidays
  • 01111111 - All days except bank holidays
  • 001110000 - Friday to Sunday and not BH

Then you can filter using the “what type of day is today” using a simple logical and.

But I guess the kids don’t get taught binary logic anymore as they’re all doing HTML/CSS and have no reason to worry about 8-bit bitmaps.

@briantist
I wonder just how many variations (and thus digits) would be required. You also have to cover "Mondays to Fridays, except on Christmas Eve (some late journeys don’t run), Sundays except Carnival weekends and goodness knows what else. I can see why someone thought it a good idea to deal with these by exception, so as to speak. It is hard for the external user to make head or tail of but I suppose much of it predates Open Data.

At least TfL doesn;pt have any “first and third Tuesdays in the month” routes!

You should try some of the TxC timetables from the BODS operators, how about a Monday - Saturday service that has a Sunday service that only runs on Bank Holidays or my favourite, a repeat of the above but specifying Bank Holidays that occur in September, October and November only. :sob: :sob: :sob: :sob:

I think for TxC you also need to factor in substitute Bank Holiday days e.g. when Christmas Day and/or Boxing Day fall on a weekend.