It's always been the case, as far as I know. You may be thinking of the fact that you can't ptrace a process that's already being ptraced, which includes processes that are ptracing themselves.
Correct, which is why I'm mentioning it here. Stracing another instance of strace does not involve any of the processes ptracing themselves, though, and I don't think it ever has.
This isn't recursion. "strace strace foo" first runs the "strace" binary (PID X), which attaches one ptrace to "foo" (PID Y) and runs an I/O loop printing retrieved trace data. The outer "strace" call launches as PID Z, and attaches a ptrace to PID Y: the inner strace. The inner strace is not itself being ptraced until that happens, so there's no special case needed to allow "stracing strace".
However, you may be referring to a different scenario: multiple ptrace calls do hit the same process if you (for example) run "strace -p PID" for the same PID more than once simultaneously. In that case, strace invocations after the first one will fail with an error like 'strace: attach: ptrace(PTRACE_SEIZE, PID): Operation not permitted'.
The only constraint is that each process (or maybe each thread, I'm not sure off the top of my head) has at most one tracer. That constraint is not violated here.
In the case of strace -> strace -> date, the middle strace has one parent and one child. That's fine.
You can even have mutually recursive ptracing (occasionally used as an anti-debug strategy), since that doesn't violate the constraint either.