Search code examples
python-3.xtimezonepytzpython-dateutil

Python Time zone conversion confusion


I have this simple function and test here:

def convert_to_current_time_zone(server_time, test_timezone = None):
  """
  Converts a time from server time to the users time zone, taking daylight savings
  time into account if relevant.
  Args:
    server_time: A string object representing server time via YYYY-MM-DD HH:mm:ss format
  Returns:
    A datetime object in the time zone the user is currently in.
  """
  global server_time_zone

  server_datetime = datetime.datetime.strptime(server_time,'%Y-%m-%d %H:%M:%S').replace(tzinfo=server_time_zone)

  if test_timezone:
    converted_datetime = server_datetime.astimezone(tz = test_timezone)
  else:
    converted_datetime = server_datetime.astimezone(tz = datetime.datetime.now().astimezone().tzinfo)

  return converted_datetime
class TimezoneConversionTest(unittest.TestCase):
  def test_day_light_savings(self):
    # Input will be the last day of September 2023, 11:31am, PDT this should
    # convert to 4:01 am ACST (ACDT) which will trigger the DST, resulting in a
    # final time of 5:01am.
    server_time = '2023-09-30 11:31:00'
    global server_time_zone
    server_time_zone = dateutil.tz.gettz('America/Los_Angeles')
    converted_time = convert_to_current_time_zone(server_time, dateutil.tz.gettz('Australia/Darwin'))
    self.assertTrue(bool(converted_time.dst()))
    self.assertEqual(converted_time.strftime('%Y-%m-%d %H:%M:%S'), "2023-10-01 05:01:00")

When I run this code I get the time 4:01. Perhaps my math is wrong but the time difference between PDT and ACST is 16.5 hours, so when 11:31 is given 16 and a half hours from then is 4:01 am the next day, however since daylights saving should of been in effect from 2am onwards of the first Sunday of October (October 1st is a Sunday) this should of triggered daylight savings to now be in effect which according to (https://www.australia.gov.au/time-zones-and-daylight-saving) should of brought the clock forward an hour.

Can anyone explain the problem here? I thought maybe it has something to do with PDT already being in effect but I can't make sense of it. Perhaps the method of calling replace then as timezone does not work as I intend. Or maybe even I can't count and it should be 4:01am 😥

Any help would be appreciated, thanks.


Solution

  • 'Australia/Darwin' is a separate timezone to 'Australia/Adelaide'. While they share ACST only 'Australia/Adelaide' has daylight savings.

    This fixes the test:

          def test_day_light_savings(self):
            # Input will be the last day of September 2023, 11:31am, PDT this should
            # convert to 4:01 am ACST (ACDT) which will trigger the DST, resulting in a
            # final time of 5:01am.
            server_time = '2023-09-30 11:31:00'
            global server_time_zone
            server_time_zone = dateutil.tz.gettz('America/Los_Angeles')
            converted_time = convert_to_current_time_zone(server_time, dateutil.tz.gettz('Australia/Adelaide'))
            self.assertTrue(bool(converted_time.dst()))
            self.assertEqual(converted_time.strftime('%Y-%m-%d %H:%M:%S'), "2023-10-01 05:01:00")