Log: libcrmcommon: improve time-as-string function
This tweaks the string so that the singular or plural is always used correctly,
spaces are added only when needed, and "<undefined time>" is used instead of
the empty string for a NULL argument.
Additionally, this does one dynamic memory allocation of exactly the amount
needed, rather than potentially multiple allocations that total more than
needed, and it asserts on memory errors so that callers can assume the return
value is non-NULL (which some already do).