Semantically: After the JOIN. But in this case, there is no difference in timing, because it's on the LEFT side of the JOIN.
As you already have it, "only rows in A from "Yesterday" are joined to B".
The optimizer is free to reorganize its order of operations depending on the equivalences in the relational algebra.
This returns only A.date="Yesterday" and joins B where it can find a match on foo:
SELECT * FROM A
LEFT JOIN B
ON A.foo=B.foo
WHERE A.date="Yesterday"
This returns all A regardless of any criteria and joins B where A.date="Yesterday" AND it finds a match on foo:
SELECT * FROM A
LEFT JOIN B
ON A.foo=B.foo
AND A.date="Yesterday"