Django ORM Запрос, агрегирующий datetime + timeoffset и фильтр по новому значению

У меня следующая структура таблицы (обратите внимание на локализованное время начала):

id start_time offset score
1 2024-06-14 02:03:00.000 +0200 +1000 15
2 2024-06-14 02:04:00.000 +0200 +1000 15
3 2024-06-14 02:05:00.000 +0200 +1000 12
4 2024-06-14 02:06:00.000 +0200 +1000 10

Я пытаюсь придумать запрос, который извлекает все записи, в которых время начала, локализованное в смещении столбца, больше заданной даты.

До сих пор я пробовал что-то вроде:

from django.db.models import F, ExpressionWrapper
from django.db import models
from django.db.models.functions import TruncDate
from datetime import datetime
import pytz

utc = pytz.timezone('UTC')

localized_start_time = ExpressionWrapper(
    TruncDate('start_time', tzinfo=utc) + F('offset'), output_field=models.DateTimeField()
)

result = MyModel.objects.annotate(
    localized_start_time=localized_start_time
).filter(
    localized_start_time=datetime.now()
)

Однако при выполнении запроса на выходе я получаю:

operator does not exist: date + character varying
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.

Подскажите, как добавить локализованное время начала, используя значение в столбце смещения?

К сожалению, я не могу изменить способ хранения данных, поскольку это производственная база данных, и последствия будут слишком большими.

Закончилось все тем, что я выполнил кучу операций кастинга:

  • Создайте выражение для преобразования смещения varchar в соответствующее смещение часов, примеры:

    • +0700 -> (substring) -> +07 -> (cast integer) -> +7
    • -0200 -> (substring) -> -02 -> (cast integer) -> -2
  • Внутренняя аннотация:

    • Приведите start_time к временной метке, чтобы удалить часовой пояс
    • Добавьте смещение из выражения выше к приведенному start_time
  • Фильтр по аннотированному значению

     # extract substring +0700 -> +07 and convert to int +7
     adjusted_offset_expr = ExpressionWrapper(
         Cast(Substr("offset", 1, 3), IntegerField())
         * Cast(timedelta(hours=1), TimeField()),
         output_field=DurationField(),
     )
    
     # cast start_time to timestamp to remove timezone
     # add offset to start_time
     activity_log = (
         MyModel.objects.annotate(
             adjusted_start_time=ExpressionWrapper(
                 Cast("start_time", DateTimeField()) + adjusted_offset_expr,
                 output_field=DateTimeField(),
             )
         )
         .filter(
             adjusted_start_time__gte=start_time.replace(tzinfo=pytz.UTC),
         ).values()
     )
    
Вернуться на верх