Code Kata - Berlin Clock
That's a lot of code for something that could be done with a single function. The number of operations required to determine the output is relatively small, so writing a whole TimeUnit class hierarchy for it is overkill. Keeping your code short and simple makes it easier to understand, which helps preventing (or spotting) bugs.

If you do want to write a utility class, then a single, configurable TimeUnit class is sufficient. The only difference between the time units are lamp color and number of lamps per row, which can be passed in via the TimeUnit constructor.

Instead of passing strings around, why not use a built-in date/time type? That, or a set of 3 integers. That will clearly communicate how the function is to be used. A string is more ambiguous: should I pass in "15:30:05", "3:30:05PM", or some other format?

The 'S' in SOLID stands for Single responsibility. Let another function do the parsing. Your function should focus on the time-to-BerlinClock-display conversion. That's also related to 'I': Interface segregation. It's better to have several classes (or functions, in this case) that each do one thing well, than one big class/function that does everything, but turns out to be very inflexible when you only need part of that 'everything'.

Remember, KISS: Keep It Short and Simple. Also, DRY: Don't Repeat Yourself.