I have been struggling with this issue for a while now. I feel that I understand Timezones well, and I think I understand how to use pytz properly so I usually use that and I typically don't have any problems. Maybe I am trying to use the wrong tools for what I want.
With my current application, I need to work in abstract time
objects. That is, I care about something that happens at 16:00. I don't care that it happens at 16:00 ON December 23rd. It seems that pytz prefers working with datetime
objects: and that makes sense. It can't figure out the offset since it's different based on the day for daylight savings and historical reasons and so on.
I'm trying to allow users to coordinate daily events all around the world. If a user in Japan says the event is from 21:00 to 23:00 every day, I want users in US/Central to see 6:00 to 8:00 every day. And I thought I had this working... until two weeks ago that is. See, DST just ended in most of the United States, so what now is 6:00-8:00 was actually previously 7:00-9:00.
This breaks my idea that I need to typically store times in UTC, then convert them only for viewing. The timezone it was created in is actually very important. If we reverse this, and a user in a US time zone that observes Daylight Savings sets an event time, that time needs to change in Japan even though they don't observe it! If I store that time as UTC, nothing changes in Japan, but that is not the functionality I want.
So I would like to store as a time
object with tzinfo
. But you can't create a time object with an accurate pytz tzinfo
without a date, but the date isn't important. If I use the current date to figure out the tzinfo
then that will actually cease to be accurate once that time zone changes.
I guess my question is: what the best way to store "4 PM Eastern" in a way that can be retrieved anywhere in the world, at any time in the future? That includes Eastern! I want it to be 4PM during DST and also outside of DST. I can't store it as UTC, because 12:00 UTC is the same time as 12:00 UTC during the entire year, but I don't want that. What I think I want is, an "abstract" or "temporary" pytz.timezone
that doesn't have an actual offset until the date (the date of viewing) is given. Is that a thing? I've read countless questions on this site, both the python and pytz docs, and can't find anything like this, or anyone with a similar problem. Everything seems to talk about specific datetimes
or working only within datetimes
but that doesn't seem relevant to my issue.
My application is pretty huge so it's hard to pull out the specific parts, but I can try to show what I've tried and why things don't work.
event_time = datetime.time(hour=12, tzinfo=pytz.timezone("US/Eastern"))
would be my ideal solution. But using pytz for tzinfo creation is not a good idea (this will give me an offset like -5:04 because of historical reasons) - is there a way to specify the version of US/Eastern to use?
datetime.now(pytz.timezone("US/Eastern")).replace(hour=12, minute=0, second=0, microsecond=0).timetz()
gives me something that looks like what I want, but it only functions correctly as long as US/Eastern doesn't change. If I apply this to a date that I have moved back before the DST change, it gives me 13:00, which is not what I want.