In a switch statement, why are all the cases being executed?

It's a bug in your code. You forgot to put in a break after each case:

switch (day % 10) {
    case 1: ordinalBuilder.append("st"); break;
    case 2: ordinalBuilder.append("nd"); break;
    case 3: ordinalBuilder.append("rd"); break;
    default: ordinalBuilder.append("th"); break;
}

I don't see any bug here, at least not in the way the language is working. The behavior of a switch statement, by design, is that it will start executing statements at the case label which matches the argument, and then continue until the end of the block. So

switch (x) {
    case 1:
        // do thing 1
    case 2:
        // do thing 2
    case 3:
        // do thing 3
    default:
        // do nothing
}

will do both things 2 and 3 if x is 2, and will do things 1, 2, and 3 if x is 1.

To get the behavior you're probably looking for, end each case with a break:

switch (x) {
    case 1:
        // do thing 1
        break;
    case 2:
        // do thing 2
        break;
    case 3:
        // do thing 3
        break;
    default:
        // do nothing
        break;
}

(strictly speaking the break at the very end is unnecessary, but I often put it in out of habit).

The reason you didn't have this problem in the first code example is that return is like a super-break: it has the same effect as break, namely ending execution within the switch block, but it also ends execution of the whole method.