Изображение ситуации, у меня есть приложение для личного календаря. Внутри есть модель, которая содержит дни, и только для моего приложения может быть вещь, которая может длиться 48 часов. Чтобы все было в порядке, мои дни не могут перекрывать друг друга - в БД есть ограничение на исключение.
Так что моя проблема в том, что когда я пытаюсь обновить свой календарь до нового часового пояса, мои дни перекрывают друг друга. Например, первый день начинается с 01:00 до 23:00 15 марта, второй день - с 00:03 до 23:30. 16 марта, когда мы переключаем часовой пояс на + -3 часа, происходит сбой:
def do_execute(self, cursor, statement, parameters, context=None):
> cursor.execute(statement, parameters)
E sqlalchemy.exc.IntegrityError: (psycopg2.errors.ExclusionViolation) conflicting key value violates exclusion constraint "days_timerange_user_id_excl"
E DETAIL: Key (timerange, user_id)=(["2014-03-15 22:45:00+00","2014-03-16 11:50:00+00"), 739) conflicts with existing key (timerange, user_id)=(["2014-03-16 04:00:00+00","2014-03-16 10:00:00+00"), 739).
E [SQL: 'UPDATE days SET timerange=%(timerange)s WHERE days.id = %(days_id)s'] [parameters: {'timerange': MutableDateTimeTZRange(datetime.datetime(2014, 3, 15, 12, 45, tzinfo=tzfile('/usr/share/zoneinfo/Pacific/Tahiti')), datetime.datetime(2014, 3, 16, 1, 50, tzinfo=tzfile('/usr/share/zoneinfo/Pacific/Tahiti')), '[)'), 'days_id': 858}] (Background on this error at: http://sqlalche.me/e/gkpj)
Мойфункция, которая делает это:
# Days
for i in user.days[::direction]:
i.timerange = change_tz_timerange(i.timerange, user.timezone, timezone)
self.request.dbsession.flush()
Я пробовал переключать направления, но это не имеет значения, когда разница часовых поясов достаточно велика.
в change_tz_timerange
вы можете увидеть:
def change_tz_timerange(timerange, old_tz, new_tz):
return DateTimeTZRange(
replace_tz(timerange.lower, old_tz, new_tz),
replace_tz(timerange.upper, old_tz, new_tz),
'[)'
)
и replace_tz
:
def replace_tz(dt, old_timezone, new_timezone):
old_tz = pytz.timezone(old_timezone)
dt = dt.astimezone(old_tz)
dt = dt.replace(tzinfo=None)
return arrow.get(dt, new_timezone).datetime
Есть ли способ обновить их все за один раз? или «удалить» их в процессе обновления? Спасибо.