def adjust_datetimes(data, parent=None, key=None, process_timezones=None): """ find all datetime-like strings within data (deserialized json) and format them uniformly, in place. this only processes timezones correctly if the call comes from a request with domain information otherwise it will default to not processing timezones. to force timezone processing, it can be called as follows >>> from corehq.apps.tzmigration.api import force_phone_timezones_should_be_processed >>> with force_phone_timezones_should_be_processed(): >>> adjust_datetimes(form_json) """ process_timezones = process_timezones or phone_timezones_should_be_processed() # this strips the timezone like we've always done # todo: in the future this will convert to UTC if isinstance(data, six.string_types) and jsonobject.re_loose_datetime.match(data): soft_assert_type_text(data) try: parent[key] = six.text_type(json_format_datetime( adjust_text_to_datetime(data, process_timezones=process_timezones) )) except iso8601.ParseError: pass elif isinstance(data, dict): for key, value in data.items(): adjust_datetimes(value, parent=data, key=key, process_timezones=process_timezones) elif isinstance(data, list): for i, value in enumerate(data): adjust_datetimes(value, parent=data, key=i, process_timezones=process_timezones) # return data, just for convenience in testing # this is the original input, modified, not a new data structure return data
def adjust_datetimes(data, parent=None, key=None, process_timezones=None): """ find all datetime-like strings within data (deserialized json) and format them uniformly, in place. this only processes timezones correctly if the call comes from a request with domain information otherwise it will default to not processing timezones. to force timezone processing, it can be called as follows >>> from corehq.apps.tzmigration.api import force_phone_timezones_should_be_processed >>> with force_phone_timezones_should_be_processed(): >>> adjust_datetimes(form_json) """ process_timezones = process_timezones or phone_timezones_should_be_processed() # this strips the timezone like we've always done # todo: in the future this will convert to UTC if isinstance(data, six.string_types) and jsonobject.re_loose_datetime.match(data): try: parent[key] = six.text_type(json_format_datetime( adjust_text_to_datetime(data, process_timezones=process_timezones) )) except iso8601.ParseError: pass elif isinstance(data, dict): for key, value in data.items(): adjust_datetimes(value, parent=data, key=key, process_timezones=process_timezones) elif isinstance(data, list): for i, value in enumerate(data): adjust_datetimes(value, parent=data, key=i, process_timezones=process_timezones) # return data, just for convenience in testing # this is the original input, modified, not a new data structure return data
def _get_expected_name(self, name, tz_differs): expected_name = name if tz_differs and phone_timezones_should_be_processed(): expected_name = name + '-tz' if getattr(settings, 'TESTS_SHOULD_USE_SQL_BACKEND', False): expected_name += '-sql' return expected_name
def test_strip_tz(self): if phone_timezones_should_be_processed(): self.assertEqual( adjust_datetimes({'datetime': '2013-03-09T06:30:09.007+03'}), {'datetime': '2013-03-09T03:30:09.007000Z'}) else: self.assertEqual( adjust_datetimes({'datetime': '2013-03-09T06:30:09.007+03'}), {'datetime': '2013-03-09T06:30:09.007000Z'})
def test_strip_tz(self): if phone_timezones_should_be_processed(): self.assertEqual( adjust_datetimes({'datetime': '2013-03-09T06:30:09.007+03'}), {'datetime': '2013-03-09T03:30:09.007000Z'} ) else: self.assertEqual( adjust_datetimes({'datetime': '2013-03-09T06:30:09.007+03'}), {'datetime': '2013-03-09T06:30:09.007000Z'} )
def adjust_text_to_datetime(text, process_timezones=None): matching_datetime = iso8601.parse_date(text) if process_timezones or phone_timezones_should_be_processed(): return matching_datetime.astimezone(pytz.utc).replace(tzinfo=None) else: return matching_datetime.replace(tzinfo=None)