1

我正在使用一个名为架构师的 python 包,它有助于在 Django 模型中使用 Postgres 分区。而且我每个月都设置了分区表。但是在检查约束中,我看到截断的日期正在移动。例如

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 代码导致了上述转变。

这是来自架构师的代码部分,它添加了检查约束。

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}') || '''';"
        ]
    }

谁能向我解释导致这种转变的原因

4

1 回答 1

0

观察这一点,2020-09-01 05:45:00+05:45并且2020-09-01 00:00:00Z在不同的时区是相同的时间点。一个是 +05:45,一个是 UTC。您的应用程序可能将其解释2020-09-01 00:00:00为 UTC,然后将其更改为应用程序的时区。

如果列是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是一个模棱两可的时间点。您的应用程序可能会将其解释为 UTC 或应用程序的时区 +05:45。它似乎将其解释为 UTC,然后将其转换为您的应用程序的时间。2020-09-01 00:00:00在 UTC 中是 2020-09-01 05:45:00+05:45.

关于时区的Django 文档似乎证实了这一点。

当启用对时区的支持时,Django 以 UTC 格式将日期时间信息存储在数据库中,在内部使用时区感知的日期时间对象,并在模板和表单中将它们转换为最终用户的时区。

我不熟悉 Django 来确切地说如何解决这个问题。在疑难解答部分有“3.now.date() 是昨天!(或明天)”关于将日期时间转换为可能相关的日期的陷阱。

于 2020-05-02T09:00:30.703 回答