Throw or reject, all the way. Libraries generally shouldn't control the process, but the other mechanisms you've identified for surfacing "hard errors" are the standard. It's on the consumer to ensure that they account for exceptional behavior where it's possible for it to occur, especially where that depends on input from the consumer.
Returning a string message is a non-standard and therefore inferior variation on proper exception raising. Ignoring or second-guessing invalid input is the stuff of which nightmares are made. Imagine somebody using your timezone code to manage flight schedules: a time and invalid timezone come in from, say, Chongqing, you've decided to ignore invalid timezones, the code returns a "UTC" time that's actually eight hours ahead, that makes it into a central database, and suddenly air traffic control's day is a lot more interesting.
Thanks for your input! I think that makes sense what you say. To explain: the original motivation behind tizo was to be as easy to use for it's use case as possible, which is why I expect a string formatted in various possible ways instead of expecting the user to do the interpreting, but that puts me into this situation where i/o becomes hard to predict.
That's understood! The important principle here is that a library shouldn't do anything surprising. Something going wrong or being irresolvable may be a surprise in one sense, but raising an error so the consumer can decide what to do about it is the expected course of action for library code in that circumstance: you're not adding another surprise on top. Conversely, hiding errors or anticipating the user may afford a pleasant surprise sometimes, but you can't guarantee that it'll always be that way.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.