Is it considered good design to compare objects of different types?

To start with, there's nothing wrong with using free functions instead of member functions, in fact it's recommended practice. See Scott Meyer's How Non-Member Functions Improve Encapsulation. You'll want to provide the comparisons in both directions though:

bool operator==(const FooType &, const BarType &);
bool operator==(const BarType &, const FooType &);

Second, it's perfectly acceptable to provide these comparisons if the comparisons make sense. The standard library for example allows you to compare std::complex values for equality with floating point, but not less-than.

The one thing you want to avoid is comparisons that don't make sense. In your example one of the time values is a double, which means the comparison would occur for any floating point or integer value once you take standard promotions into account. This is probably more than you intended since there's no way to determine if any particular value represents a time. The loss of type checking means that there's a potential for unintended bugs.


Personal vision and experience

I personally do not frown upon the comparison between different types. I even encourage it, as it may improve code readability; making what you are doing seem more logical. Outside of the basic number types, and maybe a string and a character, I find it hard to give you a logical intra-type comparison, and I don't remember having met many. I have met alot of arithmetic operators used like this though.

How to use them

You should be careful with what you are doing, they are used scarcely for a reason. If you offer a function for the comparison of two different types, the outcome should be logical and what the user intuitively expected. It is also desirelable to write good documentation for it. Mark Ransom already said it, but it is good if users can compare in both directions. If you think your comparison is not sufficiently clear enough with an operator, you should think about using a named function. This is also a very good solution if your operator can have multiple meanings.

What can go wrong

You do not have full control over what the user will do with what you have written. tletnes gave a good example of this, where two integers are compared, but the outcome has no meaning. In contradiction to this, the comparison of two different types can be very right. A float and an integer both representing seconds, can be well compared.

Arithmetic operators

Next to logical, I would like to show an intra-type example with arithmetic operators. Arithmetic operators are much like logical operators when talking about intra-type usage.

Say you have an operator + for a two dimentional vector and a square. What does this do? The user might think it scales the square, but another user is sure it translates! These kinds of issues can be very frustrating to your users. You can solve this by providing good documentation, but what I personally prefer, is specifically named functions, like Translate.

Conclusion

Intra-type logical operators can be useful and make clean code, but bad usage makes everything just more complicated.