How to create a Timezone aware Time object that works with all dates?












4















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.










share|improve this question





























    4















    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.










    share|improve this question



























      4












      4








      4








      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.










      share|improve this question
















      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.







      python-3.x pytz






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 21 '18 at 14:45







      mvanb

















      asked Nov 20 '18 at 2:38









      mvanbmvanb

      234




      234
























          2 Answers
          2






          active

          oldest

          votes


















          2














          I built a tzinfo class that automatically handles the conversion of DST. I got the idea from the USTimeZone class example in the datetime documentation.



          The trick here is the pytz timezone database has all the historical dates of when daylight savings goes into effect. That's also why when you create a datetime object without a date, it converts the DST incorrectly; it's going based off the first entry in the database.



          from datetime import datetime, tzinfo, timedelta
          import pytz

          ZERO = timedelta(0)

          def format_timedelta(td):
          if td < timedelta(0):
          return '-' + format_timedelta(-td)
          else:
          # Change this to format positive timedeltas the way you want
          return str(td)



          class WorldTimeZone(tzinfo):
          """
          A self adjusting according to DST rules in the PYTZ database tzinfo class
          See pytz.all_timezones for a list of all zone names and offsets.
          """

          def __init__(self, zone):
          """
          :param zone: (str) Proper tzdatabase timze zone name.
          """
          # initialize the pytz timezone with current time
          # this is done to avoid confusing tznames found in the start of the tz database
          # _utcoffset should always be STD rather than DST.
          self.pytzinfo = self.__getSTD(zone)
          self._utcoffset = self.pytzinfo._utcoffset


          @staticmethod
          def __getSTD(tname):
          """
          This returns a pytz timezone object normalized to standard time for the zone requested.
          If the zone does not follow DST or a future transition time cannot be found, it normalizes to NOW instead.

          :param tname: Proper timezone name found in the tzdatabase. example: "US/Central"
          """

          # This defaults to the STD time for the zone rather than current time which could be DST
          tzone = pytz.timezone(tname)
          NOW = datetime.now(tz=pytz.UTC)
          std_date = NOW
          hasdst = False
          try:
          #transitions are in UTC. They need to be converted to localtime once we find the correct STD transition.
          for utcdate, info in zip(tzone._utc_transition_times, tzone._transition_info):
          utcdate = utcdate.replace(tzinfo=pytz.UTC)
          utcoffset, dstoffset, tzname = info
          if dstoffset == ZERO:
          std_date = utcdate
          if utcdate > NOW:
          hasdst = True
          break
          except AttributeError:
          std_date = NOW
          if not hasdst:
          std_date = NOW
          std_date = tzone.normalize(std_date)
          return std_date.tzinfo

          # This needs to be dynamic because pytzinfo updates everytime .dst() is called; which is a lot.
          @property
          def _dst(self):
          return self.pytzinfo._dst

          def __repr__(self):
          # return self.pytzinfo.__repr__()
          if self._dst:
          dst = 'DST'
          else:
          dst = 'STD'
          if self._utcoffset > timedelta(seconds=0):
          msg = '<WorldTimeZone %r %s+%s %s>'
          else:
          msg = '<WorldTimeZone %r %s%s %s>'
          return msg % (self.pytzinfo.zone, self.pytzinfo._tzname,
          format_timedelta(self._utcoffset + self._dst), dst)

          def __str__(self):
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def tzname(self, dt):
          # print " TZNAME called"
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def utcoffset(self, dt):
          # print " UTCOFFSET CALLED"
          return self._utcoffset + self.dst(dt)

          def dst(self, dt):
          # print " DST CALLED"
          if dt is None or dt.tzinfo is None:
          # An exception may be sensible here, in one or both cases.
          # It depends on how you want to treat them. The default
          # fromutc() implementation (called by the default astimezone()
          # implementation) passes a datetime with dt.tzinfo is self.
          return ZERO

          assert dt.tzinfo is self # WE ASSUME THE TZINFO ON THE DATE PASSED IN IS OUR TZINFO OBJECT.
          tmpdt = self.pytzinfo.normalize(dt)
          self.pytzinfo = tmpdt.tzinfo
          return tmpdt.tzinfo._dst


          Sample code



          EST = WorldTimeZone('US/Eastern')
          PST = WorldTimeZone('US/Pacific')
          dt_dst = datetime(2018, 11, 1, 1, 30, 00)
          dt_std = datetime(2018, 11, 6, 1, 30, 00)
          est_dst = dt_dst.replace(tzinfo=EST)
          est_std = dt_std.replace(tzinfo=EST)
          pst_dst = est_dst.astimezone(PST)
          pst_std = est_std.astimezone(PST)

          print(f"{dt_dst} >> {est_dst} >> {pst_dst}")
          print(f"{dt_std} >> {est_std} >> {pst_std}")


          outputs



          2018-11-01 01:30:00 >> 2018-11-01 01:30:00-04:00 >> 2018-10-31 22:30:00-07:00
          2018-11-06 01:30:00 >> 2018-11-06 01:30:00-05:00 >> 2018-11-05 22:30:00-08:00





          share|improve this answer


























          • This is great! I think you've covered everything. Thank you so much.

            – mvanb
            Nov 23 '18 at 2:16



















          1














          It looks like pytz provides this through the 'localize' method, as suggested in `this answer.



          From the pytz documentation:




          If you insist on working with local times, this library provides a facility for constructing them unambiguously:



          loc_dt = datetime(2002, 10, 27, 1, 30, 00)
          est_dt = eastern.localize(loc_dt, is_dst=True)
          edt_dt = eastern.localize(loc_dt, is_dst=False)
          print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))
          2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500`



          By storing the local time, and the local time zone, you can then convert it when you use it, and convert it to another region's time zone.






          share|improve this answer
























          • I will try to unpack what your suggestion is, because I don't know if this addresses my problem. I think I WANT an ambiguous time. Is the suggestion to store the exact Datetime that the recurring event was created (e.g. November 20th, 4:00 PM, Eastern) then, when calculating what time to display later, you first get out the relevant hour, construct a new Datetime using the original timezone name it was created in (which might be a different offset) along with that hour, then use that new Datetime to calculate the display time for the viewer? I think that might work...

            – mvanb
            Nov 21 '18 at 4:39











          • Hi manvb, I think you've explained it correctly. In your example, you want the 4PM appointment to stay at 4PM, even if DST changes. How would this affect the appointment in a non-DST time zone, or would this problem come up at all? For example, will a user in the eastern US time zone and in Japan interact with the same event?

            – Peanut Butter Vibes
            Nov 21 '18 at 17:22






          • 1





            Yes, exactly! Everyone should be attending the same event at the same time together, but for the creator, it will always be at the time it was defined, regardless of DST.

            – mvanb
            Nov 22 '18 at 17:29











          • I think Marcel's answer should probably work here; my thought was to store 'loc_dt' without a date, check for DST, then localize the local_dt of the event creator with the correct DST value. Finally, this time could be converted to other time zones for attendees of event. Marcel's answer handles all the ambiguities in his custom class.

            – Peanut Butter Vibes
            Nov 22 '18 at 18:10











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385422%2fhow-to-create-a-timezone-aware-time-object-that-works-with-all-dates%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          I built a tzinfo class that automatically handles the conversion of DST. I got the idea from the USTimeZone class example in the datetime documentation.



          The trick here is the pytz timezone database has all the historical dates of when daylight savings goes into effect. That's also why when you create a datetime object without a date, it converts the DST incorrectly; it's going based off the first entry in the database.



          from datetime import datetime, tzinfo, timedelta
          import pytz

          ZERO = timedelta(0)

          def format_timedelta(td):
          if td < timedelta(0):
          return '-' + format_timedelta(-td)
          else:
          # Change this to format positive timedeltas the way you want
          return str(td)



          class WorldTimeZone(tzinfo):
          """
          A self adjusting according to DST rules in the PYTZ database tzinfo class
          See pytz.all_timezones for a list of all zone names and offsets.
          """

          def __init__(self, zone):
          """
          :param zone: (str) Proper tzdatabase timze zone name.
          """
          # initialize the pytz timezone with current time
          # this is done to avoid confusing tznames found in the start of the tz database
          # _utcoffset should always be STD rather than DST.
          self.pytzinfo = self.__getSTD(zone)
          self._utcoffset = self.pytzinfo._utcoffset


          @staticmethod
          def __getSTD(tname):
          """
          This returns a pytz timezone object normalized to standard time for the zone requested.
          If the zone does not follow DST or a future transition time cannot be found, it normalizes to NOW instead.

          :param tname: Proper timezone name found in the tzdatabase. example: "US/Central"
          """

          # This defaults to the STD time for the zone rather than current time which could be DST
          tzone = pytz.timezone(tname)
          NOW = datetime.now(tz=pytz.UTC)
          std_date = NOW
          hasdst = False
          try:
          #transitions are in UTC. They need to be converted to localtime once we find the correct STD transition.
          for utcdate, info in zip(tzone._utc_transition_times, tzone._transition_info):
          utcdate = utcdate.replace(tzinfo=pytz.UTC)
          utcoffset, dstoffset, tzname = info
          if dstoffset == ZERO:
          std_date = utcdate
          if utcdate > NOW:
          hasdst = True
          break
          except AttributeError:
          std_date = NOW
          if not hasdst:
          std_date = NOW
          std_date = tzone.normalize(std_date)
          return std_date.tzinfo

          # This needs to be dynamic because pytzinfo updates everytime .dst() is called; which is a lot.
          @property
          def _dst(self):
          return self.pytzinfo._dst

          def __repr__(self):
          # return self.pytzinfo.__repr__()
          if self._dst:
          dst = 'DST'
          else:
          dst = 'STD'
          if self._utcoffset > timedelta(seconds=0):
          msg = '<WorldTimeZone %r %s+%s %s>'
          else:
          msg = '<WorldTimeZone %r %s%s %s>'
          return msg % (self.pytzinfo.zone, self.pytzinfo._tzname,
          format_timedelta(self._utcoffset + self._dst), dst)

          def __str__(self):
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def tzname(self, dt):
          # print " TZNAME called"
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def utcoffset(self, dt):
          # print " UTCOFFSET CALLED"
          return self._utcoffset + self.dst(dt)

          def dst(self, dt):
          # print " DST CALLED"
          if dt is None or dt.tzinfo is None:
          # An exception may be sensible here, in one or both cases.
          # It depends on how you want to treat them. The default
          # fromutc() implementation (called by the default astimezone()
          # implementation) passes a datetime with dt.tzinfo is self.
          return ZERO

          assert dt.tzinfo is self # WE ASSUME THE TZINFO ON THE DATE PASSED IN IS OUR TZINFO OBJECT.
          tmpdt = self.pytzinfo.normalize(dt)
          self.pytzinfo = tmpdt.tzinfo
          return tmpdt.tzinfo._dst


          Sample code



          EST = WorldTimeZone('US/Eastern')
          PST = WorldTimeZone('US/Pacific')
          dt_dst = datetime(2018, 11, 1, 1, 30, 00)
          dt_std = datetime(2018, 11, 6, 1, 30, 00)
          est_dst = dt_dst.replace(tzinfo=EST)
          est_std = dt_std.replace(tzinfo=EST)
          pst_dst = est_dst.astimezone(PST)
          pst_std = est_std.astimezone(PST)

          print(f"{dt_dst} >> {est_dst} >> {pst_dst}")
          print(f"{dt_std} >> {est_std} >> {pst_std}")


          outputs



          2018-11-01 01:30:00 >> 2018-11-01 01:30:00-04:00 >> 2018-10-31 22:30:00-07:00
          2018-11-06 01:30:00 >> 2018-11-06 01:30:00-05:00 >> 2018-11-05 22:30:00-08:00





          share|improve this answer


























          • This is great! I think you've covered everything. Thank you so much.

            – mvanb
            Nov 23 '18 at 2:16
















          2














          I built a tzinfo class that automatically handles the conversion of DST. I got the idea from the USTimeZone class example in the datetime documentation.



          The trick here is the pytz timezone database has all the historical dates of when daylight savings goes into effect. That's also why when you create a datetime object without a date, it converts the DST incorrectly; it's going based off the first entry in the database.



          from datetime import datetime, tzinfo, timedelta
          import pytz

          ZERO = timedelta(0)

          def format_timedelta(td):
          if td < timedelta(0):
          return '-' + format_timedelta(-td)
          else:
          # Change this to format positive timedeltas the way you want
          return str(td)



          class WorldTimeZone(tzinfo):
          """
          A self adjusting according to DST rules in the PYTZ database tzinfo class
          See pytz.all_timezones for a list of all zone names and offsets.
          """

          def __init__(self, zone):
          """
          :param zone: (str) Proper tzdatabase timze zone name.
          """
          # initialize the pytz timezone with current time
          # this is done to avoid confusing tznames found in the start of the tz database
          # _utcoffset should always be STD rather than DST.
          self.pytzinfo = self.__getSTD(zone)
          self._utcoffset = self.pytzinfo._utcoffset


          @staticmethod
          def __getSTD(tname):
          """
          This returns a pytz timezone object normalized to standard time for the zone requested.
          If the zone does not follow DST or a future transition time cannot be found, it normalizes to NOW instead.

          :param tname: Proper timezone name found in the tzdatabase. example: "US/Central"
          """

          # This defaults to the STD time for the zone rather than current time which could be DST
          tzone = pytz.timezone(tname)
          NOW = datetime.now(tz=pytz.UTC)
          std_date = NOW
          hasdst = False
          try:
          #transitions are in UTC. They need to be converted to localtime once we find the correct STD transition.
          for utcdate, info in zip(tzone._utc_transition_times, tzone._transition_info):
          utcdate = utcdate.replace(tzinfo=pytz.UTC)
          utcoffset, dstoffset, tzname = info
          if dstoffset == ZERO:
          std_date = utcdate
          if utcdate > NOW:
          hasdst = True
          break
          except AttributeError:
          std_date = NOW
          if not hasdst:
          std_date = NOW
          std_date = tzone.normalize(std_date)
          return std_date.tzinfo

          # This needs to be dynamic because pytzinfo updates everytime .dst() is called; which is a lot.
          @property
          def _dst(self):
          return self.pytzinfo._dst

          def __repr__(self):
          # return self.pytzinfo.__repr__()
          if self._dst:
          dst = 'DST'
          else:
          dst = 'STD'
          if self._utcoffset > timedelta(seconds=0):
          msg = '<WorldTimeZone %r %s+%s %s>'
          else:
          msg = '<WorldTimeZone %r %s%s %s>'
          return msg % (self.pytzinfo.zone, self.pytzinfo._tzname,
          format_timedelta(self._utcoffset + self._dst), dst)

          def __str__(self):
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def tzname(self, dt):
          # print " TZNAME called"
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def utcoffset(self, dt):
          # print " UTCOFFSET CALLED"
          return self._utcoffset + self.dst(dt)

          def dst(self, dt):
          # print " DST CALLED"
          if dt is None or dt.tzinfo is None:
          # An exception may be sensible here, in one or both cases.
          # It depends on how you want to treat them. The default
          # fromutc() implementation (called by the default astimezone()
          # implementation) passes a datetime with dt.tzinfo is self.
          return ZERO

          assert dt.tzinfo is self # WE ASSUME THE TZINFO ON THE DATE PASSED IN IS OUR TZINFO OBJECT.
          tmpdt = self.pytzinfo.normalize(dt)
          self.pytzinfo = tmpdt.tzinfo
          return tmpdt.tzinfo._dst


          Sample code



          EST = WorldTimeZone('US/Eastern')
          PST = WorldTimeZone('US/Pacific')
          dt_dst = datetime(2018, 11, 1, 1, 30, 00)
          dt_std = datetime(2018, 11, 6, 1, 30, 00)
          est_dst = dt_dst.replace(tzinfo=EST)
          est_std = dt_std.replace(tzinfo=EST)
          pst_dst = est_dst.astimezone(PST)
          pst_std = est_std.astimezone(PST)

          print(f"{dt_dst} >> {est_dst} >> {pst_dst}")
          print(f"{dt_std} >> {est_std} >> {pst_std}")


          outputs



          2018-11-01 01:30:00 >> 2018-11-01 01:30:00-04:00 >> 2018-10-31 22:30:00-07:00
          2018-11-06 01:30:00 >> 2018-11-06 01:30:00-05:00 >> 2018-11-05 22:30:00-08:00





          share|improve this answer


























          • This is great! I think you've covered everything. Thank you so much.

            – mvanb
            Nov 23 '18 at 2:16














          2












          2








          2







          I built a tzinfo class that automatically handles the conversion of DST. I got the idea from the USTimeZone class example in the datetime documentation.



          The trick here is the pytz timezone database has all the historical dates of when daylight savings goes into effect. That's also why when you create a datetime object without a date, it converts the DST incorrectly; it's going based off the first entry in the database.



          from datetime import datetime, tzinfo, timedelta
          import pytz

          ZERO = timedelta(0)

          def format_timedelta(td):
          if td < timedelta(0):
          return '-' + format_timedelta(-td)
          else:
          # Change this to format positive timedeltas the way you want
          return str(td)



          class WorldTimeZone(tzinfo):
          """
          A self adjusting according to DST rules in the PYTZ database tzinfo class
          See pytz.all_timezones for a list of all zone names and offsets.
          """

          def __init__(self, zone):
          """
          :param zone: (str) Proper tzdatabase timze zone name.
          """
          # initialize the pytz timezone with current time
          # this is done to avoid confusing tznames found in the start of the tz database
          # _utcoffset should always be STD rather than DST.
          self.pytzinfo = self.__getSTD(zone)
          self._utcoffset = self.pytzinfo._utcoffset


          @staticmethod
          def __getSTD(tname):
          """
          This returns a pytz timezone object normalized to standard time for the zone requested.
          If the zone does not follow DST or a future transition time cannot be found, it normalizes to NOW instead.

          :param tname: Proper timezone name found in the tzdatabase. example: "US/Central"
          """

          # This defaults to the STD time for the zone rather than current time which could be DST
          tzone = pytz.timezone(tname)
          NOW = datetime.now(tz=pytz.UTC)
          std_date = NOW
          hasdst = False
          try:
          #transitions are in UTC. They need to be converted to localtime once we find the correct STD transition.
          for utcdate, info in zip(tzone._utc_transition_times, tzone._transition_info):
          utcdate = utcdate.replace(tzinfo=pytz.UTC)
          utcoffset, dstoffset, tzname = info
          if dstoffset == ZERO:
          std_date = utcdate
          if utcdate > NOW:
          hasdst = True
          break
          except AttributeError:
          std_date = NOW
          if not hasdst:
          std_date = NOW
          std_date = tzone.normalize(std_date)
          return std_date.tzinfo

          # This needs to be dynamic because pytzinfo updates everytime .dst() is called; which is a lot.
          @property
          def _dst(self):
          return self.pytzinfo._dst

          def __repr__(self):
          # return self.pytzinfo.__repr__()
          if self._dst:
          dst = 'DST'
          else:
          dst = 'STD'
          if self._utcoffset > timedelta(seconds=0):
          msg = '<WorldTimeZone %r %s+%s %s>'
          else:
          msg = '<WorldTimeZone %r %s%s %s>'
          return msg % (self.pytzinfo.zone, self.pytzinfo._tzname,
          format_timedelta(self._utcoffset + self._dst), dst)

          def __str__(self):
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def tzname(self, dt):
          # print " TZNAME called"
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def utcoffset(self, dt):
          # print " UTCOFFSET CALLED"
          return self._utcoffset + self.dst(dt)

          def dst(self, dt):
          # print " DST CALLED"
          if dt is None or dt.tzinfo is None:
          # An exception may be sensible here, in one or both cases.
          # It depends on how you want to treat them. The default
          # fromutc() implementation (called by the default astimezone()
          # implementation) passes a datetime with dt.tzinfo is self.
          return ZERO

          assert dt.tzinfo is self # WE ASSUME THE TZINFO ON THE DATE PASSED IN IS OUR TZINFO OBJECT.
          tmpdt = self.pytzinfo.normalize(dt)
          self.pytzinfo = tmpdt.tzinfo
          return tmpdt.tzinfo._dst


          Sample code



          EST = WorldTimeZone('US/Eastern')
          PST = WorldTimeZone('US/Pacific')
          dt_dst = datetime(2018, 11, 1, 1, 30, 00)
          dt_std = datetime(2018, 11, 6, 1, 30, 00)
          est_dst = dt_dst.replace(tzinfo=EST)
          est_std = dt_std.replace(tzinfo=EST)
          pst_dst = est_dst.astimezone(PST)
          pst_std = est_std.astimezone(PST)

          print(f"{dt_dst} >> {est_dst} >> {pst_dst}")
          print(f"{dt_std} >> {est_std} >> {pst_std}")


          outputs



          2018-11-01 01:30:00 >> 2018-11-01 01:30:00-04:00 >> 2018-10-31 22:30:00-07:00
          2018-11-06 01:30:00 >> 2018-11-06 01:30:00-05:00 >> 2018-11-05 22:30:00-08:00





          share|improve this answer















          I built a tzinfo class that automatically handles the conversion of DST. I got the idea from the USTimeZone class example in the datetime documentation.



          The trick here is the pytz timezone database has all the historical dates of when daylight savings goes into effect. That's also why when you create a datetime object without a date, it converts the DST incorrectly; it's going based off the first entry in the database.



          from datetime import datetime, tzinfo, timedelta
          import pytz

          ZERO = timedelta(0)

          def format_timedelta(td):
          if td < timedelta(0):
          return '-' + format_timedelta(-td)
          else:
          # Change this to format positive timedeltas the way you want
          return str(td)



          class WorldTimeZone(tzinfo):
          """
          A self adjusting according to DST rules in the PYTZ database tzinfo class
          See pytz.all_timezones for a list of all zone names and offsets.
          """

          def __init__(self, zone):
          """
          :param zone: (str) Proper tzdatabase timze zone name.
          """
          # initialize the pytz timezone with current time
          # this is done to avoid confusing tznames found in the start of the tz database
          # _utcoffset should always be STD rather than DST.
          self.pytzinfo = self.__getSTD(zone)
          self._utcoffset = self.pytzinfo._utcoffset


          @staticmethod
          def __getSTD(tname):
          """
          This returns a pytz timezone object normalized to standard time for the zone requested.
          If the zone does not follow DST or a future transition time cannot be found, it normalizes to NOW instead.

          :param tname: Proper timezone name found in the tzdatabase. example: "US/Central"
          """

          # This defaults to the STD time for the zone rather than current time which could be DST
          tzone = pytz.timezone(tname)
          NOW = datetime.now(tz=pytz.UTC)
          std_date = NOW
          hasdst = False
          try:
          #transitions are in UTC. They need to be converted to localtime once we find the correct STD transition.
          for utcdate, info in zip(tzone._utc_transition_times, tzone._transition_info):
          utcdate = utcdate.replace(tzinfo=pytz.UTC)
          utcoffset, dstoffset, tzname = info
          if dstoffset == ZERO:
          std_date = utcdate
          if utcdate > NOW:
          hasdst = True
          break
          except AttributeError:
          std_date = NOW
          if not hasdst:
          std_date = NOW
          std_date = tzone.normalize(std_date)
          return std_date.tzinfo

          # This needs to be dynamic because pytzinfo updates everytime .dst() is called; which is a lot.
          @property
          def _dst(self):
          return self.pytzinfo._dst

          def __repr__(self):
          # return self.pytzinfo.__repr__()
          if self._dst:
          dst = 'DST'
          else:
          dst = 'STD'
          if self._utcoffset > timedelta(seconds=0):
          msg = '<WorldTimeZone %r %s+%s %s>'
          else:
          msg = '<WorldTimeZone %r %s%s %s>'
          return msg % (self.pytzinfo.zone, self.pytzinfo._tzname,
          format_timedelta(self._utcoffset + self._dst), dst)

          def __str__(self):
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def tzname(self, dt):
          # print " TZNAME called"
          return "%s %s" % (self.pytzinfo._tzname, self.pytzinfo)

          def utcoffset(self, dt):
          # print " UTCOFFSET CALLED"
          return self._utcoffset + self.dst(dt)

          def dst(self, dt):
          # print " DST CALLED"
          if dt is None or dt.tzinfo is None:
          # An exception may be sensible here, in one or both cases.
          # It depends on how you want to treat them. The default
          # fromutc() implementation (called by the default astimezone()
          # implementation) passes a datetime with dt.tzinfo is self.
          return ZERO

          assert dt.tzinfo is self # WE ASSUME THE TZINFO ON THE DATE PASSED IN IS OUR TZINFO OBJECT.
          tmpdt = self.pytzinfo.normalize(dt)
          self.pytzinfo = tmpdt.tzinfo
          return tmpdt.tzinfo._dst


          Sample code



          EST = WorldTimeZone('US/Eastern')
          PST = WorldTimeZone('US/Pacific')
          dt_dst = datetime(2018, 11, 1, 1, 30, 00)
          dt_std = datetime(2018, 11, 6, 1, 30, 00)
          est_dst = dt_dst.replace(tzinfo=EST)
          est_std = dt_std.replace(tzinfo=EST)
          pst_dst = est_dst.astimezone(PST)
          pst_std = est_std.astimezone(PST)

          print(f"{dt_dst} >> {est_dst} >> {pst_dst}")
          print(f"{dt_std} >> {est_std} >> {pst_std}")


          outputs



          2018-11-01 01:30:00 >> 2018-11-01 01:30:00-04:00 >> 2018-10-31 22:30:00-07:00
          2018-11-06 01:30:00 >> 2018-11-06 01:30:00-05:00 >> 2018-11-05 22:30:00-08:00






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 21 '18 at 18:43

























          answered Nov 21 '18 at 18:19









          Marcel WilsonMarcel Wilson

          1,4891131




          1,4891131













          • This is great! I think you've covered everything. Thank you so much.

            – mvanb
            Nov 23 '18 at 2:16



















          • This is great! I think you've covered everything. Thank you so much.

            – mvanb
            Nov 23 '18 at 2:16

















          This is great! I think you've covered everything. Thank you so much.

          – mvanb
          Nov 23 '18 at 2:16





          This is great! I think you've covered everything. Thank you so much.

          – mvanb
          Nov 23 '18 at 2:16













          1














          It looks like pytz provides this through the 'localize' method, as suggested in `this answer.



          From the pytz documentation:




          If you insist on working with local times, this library provides a facility for constructing them unambiguously:



          loc_dt = datetime(2002, 10, 27, 1, 30, 00)
          est_dt = eastern.localize(loc_dt, is_dst=True)
          edt_dt = eastern.localize(loc_dt, is_dst=False)
          print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))
          2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500`



          By storing the local time, and the local time zone, you can then convert it when you use it, and convert it to another region's time zone.






          share|improve this answer
























          • I will try to unpack what your suggestion is, because I don't know if this addresses my problem. I think I WANT an ambiguous time. Is the suggestion to store the exact Datetime that the recurring event was created (e.g. November 20th, 4:00 PM, Eastern) then, when calculating what time to display later, you first get out the relevant hour, construct a new Datetime using the original timezone name it was created in (which might be a different offset) along with that hour, then use that new Datetime to calculate the display time for the viewer? I think that might work...

            – mvanb
            Nov 21 '18 at 4:39











          • Hi manvb, I think you've explained it correctly. In your example, you want the 4PM appointment to stay at 4PM, even if DST changes. How would this affect the appointment in a non-DST time zone, or would this problem come up at all? For example, will a user in the eastern US time zone and in Japan interact with the same event?

            – Peanut Butter Vibes
            Nov 21 '18 at 17:22






          • 1





            Yes, exactly! Everyone should be attending the same event at the same time together, but for the creator, it will always be at the time it was defined, regardless of DST.

            – mvanb
            Nov 22 '18 at 17:29











          • I think Marcel's answer should probably work here; my thought was to store 'loc_dt' without a date, check for DST, then localize the local_dt of the event creator with the correct DST value. Finally, this time could be converted to other time zones for attendees of event. Marcel's answer handles all the ambiguities in his custom class.

            – Peanut Butter Vibes
            Nov 22 '18 at 18:10
















          1














          It looks like pytz provides this through the 'localize' method, as suggested in `this answer.



          From the pytz documentation:




          If you insist on working with local times, this library provides a facility for constructing them unambiguously:



          loc_dt = datetime(2002, 10, 27, 1, 30, 00)
          est_dt = eastern.localize(loc_dt, is_dst=True)
          edt_dt = eastern.localize(loc_dt, is_dst=False)
          print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))
          2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500`



          By storing the local time, and the local time zone, you can then convert it when you use it, and convert it to another region's time zone.






          share|improve this answer
























          • I will try to unpack what your suggestion is, because I don't know if this addresses my problem. I think I WANT an ambiguous time. Is the suggestion to store the exact Datetime that the recurring event was created (e.g. November 20th, 4:00 PM, Eastern) then, when calculating what time to display later, you first get out the relevant hour, construct a new Datetime using the original timezone name it was created in (which might be a different offset) along with that hour, then use that new Datetime to calculate the display time for the viewer? I think that might work...

            – mvanb
            Nov 21 '18 at 4:39











          • Hi manvb, I think you've explained it correctly. In your example, you want the 4PM appointment to stay at 4PM, even if DST changes. How would this affect the appointment in a non-DST time zone, or would this problem come up at all? For example, will a user in the eastern US time zone and in Japan interact with the same event?

            – Peanut Butter Vibes
            Nov 21 '18 at 17:22






          • 1





            Yes, exactly! Everyone should be attending the same event at the same time together, but for the creator, it will always be at the time it was defined, regardless of DST.

            – mvanb
            Nov 22 '18 at 17:29











          • I think Marcel's answer should probably work here; my thought was to store 'loc_dt' without a date, check for DST, then localize the local_dt of the event creator with the correct DST value. Finally, this time could be converted to other time zones for attendees of event. Marcel's answer handles all the ambiguities in his custom class.

            – Peanut Butter Vibes
            Nov 22 '18 at 18:10














          1












          1








          1







          It looks like pytz provides this through the 'localize' method, as suggested in `this answer.



          From the pytz documentation:




          If you insist on working with local times, this library provides a facility for constructing them unambiguously:



          loc_dt = datetime(2002, 10, 27, 1, 30, 00)
          est_dt = eastern.localize(loc_dt, is_dst=True)
          edt_dt = eastern.localize(loc_dt, is_dst=False)
          print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))
          2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500`



          By storing the local time, and the local time zone, you can then convert it when you use it, and convert it to another region's time zone.






          share|improve this answer













          It looks like pytz provides this through the 'localize' method, as suggested in `this answer.



          From the pytz documentation:




          If you insist on working with local times, this library provides a facility for constructing them unambiguously:



          loc_dt = datetime(2002, 10, 27, 1, 30, 00)
          est_dt = eastern.localize(loc_dt, is_dst=True)
          edt_dt = eastern.localize(loc_dt, is_dst=False)
          print(est_dt.strftime(fmt) + ' / ' + edt_dt.strftime(fmt))
          2002-10-27 01:30:00 EDT-0400 / 2002-10-27 01:30:00 EST-0500`



          By storing the local time, and the local time zone, you can then convert it when you use it, and convert it to another region's time zone.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 20 '18 at 3:29









          Peanut Butter VibesPeanut Butter Vibes

          1429




          1429













          • I will try to unpack what your suggestion is, because I don't know if this addresses my problem. I think I WANT an ambiguous time. Is the suggestion to store the exact Datetime that the recurring event was created (e.g. November 20th, 4:00 PM, Eastern) then, when calculating what time to display later, you first get out the relevant hour, construct a new Datetime using the original timezone name it was created in (which might be a different offset) along with that hour, then use that new Datetime to calculate the display time for the viewer? I think that might work...

            – mvanb
            Nov 21 '18 at 4:39











          • Hi manvb, I think you've explained it correctly. In your example, you want the 4PM appointment to stay at 4PM, even if DST changes. How would this affect the appointment in a non-DST time zone, or would this problem come up at all? For example, will a user in the eastern US time zone and in Japan interact with the same event?

            – Peanut Butter Vibes
            Nov 21 '18 at 17:22






          • 1





            Yes, exactly! Everyone should be attending the same event at the same time together, but for the creator, it will always be at the time it was defined, regardless of DST.

            – mvanb
            Nov 22 '18 at 17:29











          • I think Marcel's answer should probably work here; my thought was to store 'loc_dt' without a date, check for DST, then localize the local_dt of the event creator with the correct DST value. Finally, this time could be converted to other time zones for attendees of event. Marcel's answer handles all the ambiguities in his custom class.

            – Peanut Butter Vibes
            Nov 22 '18 at 18:10



















          • I will try to unpack what your suggestion is, because I don't know if this addresses my problem. I think I WANT an ambiguous time. Is the suggestion to store the exact Datetime that the recurring event was created (e.g. November 20th, 4:00 PM, Eastern) then, when calculating what time to display later, you first get out the relevant hour, construct a new Datetime using the original timezone name it was created in (which might be a different offset) along with that hour, then use that new Datetime to calculate the display time for the viewer? I think that might work...

            – mvanb
            Nov 21 '18 at 4:39











          • Hi manvb, I think you've explained it correctly. In your example, you want the 4PM appointment to stay at 4PM, even if DST changes. How would this affect the appointment in a non-DST time zone, or would this problem come up at all? For example, will a user in the eastern US time zone and in Japan interact with the same event?

            – Peanut Butter Vibes
            Nov 21 '18 at 17:22






          • 1





            Yes, exactly! Everyone should be attending the same event at the same time together, but for the creator, it will always be at the time it was defined, regardless of DST.

            – mvanb
            Nov 22 '18 at 17:29











          • I think Marcel's answer should probably work here; my thought was to store 'loc_dt' without a date, check for DST, then localize the local_dt of the event creator with the correct DST value. Finally, this time could be converted to other time zones for attendees of event. Marcel's answer handles all the ambiguities in his custom class.

            – Peanut Butter Vibes
            Nov 22 '18 at 18:10

















          I will try to unpack what your suggestion is, because I don't know if this addresses my problem. I think I WANT an ambiguous time. Is the suggestion to store the exact Datetime that the recurring event was created (e.g. November 20th, 4:00 PM, Eastern) then, when calculating what time to display later, you first get out the relevant hour, construct a new Datetime using the original timezone name it was created in (which might be a different offset) along with that hour, then use that new Datetime to calculate the display time for the viewer? I think that might work...

          – mvanb
          Nov 21 '18 at 4:39





          I will try to unpack what your suggestion is, because I don't know if this addresses my problem. I think I WANT an ambiguous time. Is the suggestion to store the exact Datetime that the recurring event was created (e.g. November 20th, 4:00 PM, Eastern) then, when calculating what time to display later, you first get out the relevant hour, construct a new Datetime using the original timezone name it was created in (which might be a different offset) along with that hour, then use that new Datetime to calculate the display time for the viewer? I think that might work...

          – mvanb
          Nov 21 '18 at 4:39













          Hi manvb, I think you've explained it correctly. In your example, you want the 4PM appointment to stay at 4PM, even if DST changes. How would this affect the appointment in a non-DST time zone, or would this problem come up at all? For example, will a user in the eastern US time zone and in Japan interact with the same event?

          – Peanut Butter Vibes
          Nov 21 '18 at 17:22





          Hi manvb, I think you've explained it correctly. In your example, you want the 4PM appointment to stay at 4PM, even if DST changes. How would this affect the appointment in a non-DST time zone, or would this problem come up at all? For example, will a user in the eastern US time zone and in Japan interact with the same event?

          – Peanut Butter Vibes
          Nov 21 '18 at 17:22




          1




          1





          Yes, exactly! Everyone should be attending the same event at the same time together, but for the creator, it will always be at the time it was defined, regardless of DST.

          – mvanb
          Nov 22 '18 at 17:29





          Yes, exactly! Everyone should be attending the same event at the same time together, but for the creator, it will always be at the time it was defined, regardless of DST.

          – mvanb
          Nov 22 '18 at 17:29













          I think Marcel's answer should probably work here; my thought was to store 'loc_dt' without a date, check for DST, then localize the local_dt of the event creator with the correct DST value. Finally, this time could be converted to other time zones for attendees of event. Marcel's answer handles all the ambiguities in his custom class.

          – Peanut Butter Vibes
          Nov 22 '18 at 18:10





          I think Marcel's answer should probably work here; my thought was to store 'loc_dt' without a date, check for DST, then localize the local_dt of the event creator with the correct DST value. Finally, this time could be converted to other time zones for attendees of event. Marcel's answer handles all the ambiguities in his custom class.

          – Peanut Butter Vibes
          Nov 22 '18 at 18:10


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53385422%2fhow-to-create-a-timezone-aware-time-object-that-works-with-all-dates%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          MongoDB - Not Authorized To Execute Command

          How to fix TextFormField cause rebuild widget in Flutter

          in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith