This means that while there is fancy object-oriented code-reuse arm-waving, if you actually try to use these classes in a generic manner things fail mysteriously. This is fundamental breakage in the design. First they "enforce type-safety" then if you actually rely upon type-safey you get bit in the ass.
This is documented (from http://docs.oracle.com/javase/7/docs/api/java/sql/Timestamp.html):
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.This gets me in a lather. Clearly being a child of java.util.Date means nothing.
What they should have done was have a Date-like interface specifying the getTime()/setTime(long) functions and defined that they accepted time in milliseconds and their epoch. Then we could use any getTime()/setTime() related function the same without caring about the advanced features it possessed.
As it is there are too many different ways to specify dates and they're all incompatible. It's almost easier to pass time around in milliseconds and convert to the desired type as-needed.