Postgres DATE_TRUN C смещает отметку времени - PullRequest
1 голос
/ 02 мая 2020

Я использую пакет python под названием architect, который помогает использовать Postgres раздел в модели Django И я создал таблицу разделов для каждого месяца. Но в проверочных ограничениях я вижу, что усеченная дата смещается. Например,

DATE_TRUNC('month','2020-09-12 15:23:00+05:45') дает 2020-09-01 05:45:00+05:45

. Из-за этого проверочные ограничения становятся

CONSTRAINT "transactionservice_transaction_y2020m09_TransactionDate_check" CHECK ("TransactionDate" >= '2020-09-01 05:45:00+05:45'::timestamp with time zone AND "TransactionDate" < '2020-10-01 05:45:00+05:45'::timestamp with time zone)
)

. В результате транзакция с 2020-9-1 02:03:33 находится внутри Таблица транзакций 2020-08 Это не то, что я хочу.

Я попробовал это из pgadmin, и вывод 2020-09-01 00:00:00+05:45, что я исключаю.

Но код sql выполнен из пакета architect приводит к приведенному выше сдвигу.

Вот часть кода от architect, которая добавляет контрольное ограничение.

def _get_date_definitions(self):
    """
    Returns definitions for date partition subtype.
    """
    patterns = {
        'day': '"y"YYYY"d"DDD',
        'week': '"y"IYYY"w"IW',
        'month': '"y"YYYY"m"MM',
        'year': '"y"YYYY',
    }
    try:
        pattern = patterns[self.constraint]
    except KeyError:
        raise PartitionConstraintError(
            model=self.model.__name__,
            dialect=self.dialect,
            current=self.constraint,
            allowed=patterns.keys())
    return {
        'formatters': {'pattern': pattern},
        'variables': [
            "match := DATE_TRUNC('{constraint}', NEW.{{column}});",
            "tablename := '{{parent_table}}_' || TO_CHAR(NEW.{{column}}, '{pattern}');",
            "checks := '{{column}} >= ''' || match || ''' AND {{column}} < ''' || (match + INTERVAL '1 {constraint}') || '''';"
        ]
    }

Может кто-нибудь объяснить мне, что вызывает сдвиг

1 Ответ

0 голосов
/ 02 мая 2020

Обратите внимание, что 2020-09-01 05:45:00+05:45 и 2020-09-01 00:00:00Z - это один и тот же момент времени в разных часовых поясах. Один в +05: 45, а другой в UT C. Вероятно, ваше приложение интерпретирует 2020-09-01 00:00:00 как UT C, а затем изменяет его на часовой пояс приложения.

Если столбец представляет собой timestamp без часового пояса, date_trunc создаст временную метку с нет зоны. Мой часовой пояс -0700.

select date_trunc('month', timestamp '2020-09-12 15:23:00+05:45')
2020-09-01 00:00:00

select date_trunc('month', timestamptz '2020-09-12 15:23:00+05:45')
2020-09-01 00:00:00-07

2020-09-01 00:00:00 - это неоднозначный момент времени. Ваше приложение может интерпретировать его как UT C или в часовом поясе вашего приложения +05: 45. Кажется, он интерпретируется как UT C, а затем переводится во время вашего приложения. 2020-09-01 00:00:00 в UT C - это 2020-09-01 05:45:00+05:45.

Документация Django о часовых поясах , кажется, подтверждает это.

Когда включена поддержка часовых поясов, Django сохраняет информацию о дате и времени в UT C в базе данных, использует объекты datetime с учетом часовых поясов для внутреннего использования, и переводит их в часовой пояс конечного пользователя в шаблонах и формах.

Я не знаком с Django, чтобы точно сказать, как решить эту проблему. В разделе Устранение неполадок есть «3. now.date () вчера! (Или завтра)» о ловушках преобразования даты и времени в дату, которая может иметь значение.

...