有没有一种方法可以将SQLAlchemy中的日期时间截断为小时/天/ 周 /月/年,从而适用于所有DBMS(尤其是Postgres和SQLite)?
Not out of the box, but you could make one (I suppose this is related to this ):
from sqlalchemy import func
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import ColumnElement
from sqlalchemy.types import DateTime
class Trunc(ColumnElement):
type = DateTime()
def __init__(self, precision, expr):
self.precision = precision
self.expr = expr
@property
def _from_objects(self):
return self.expr._from_objects
The compiler for Postgresql is simple:
@compiles(Trunc, 'postgresql')
def compile_trunc_postgresql(element, compiler, **kw):
return compiler.process(func.date_trunc(element.precision, element.expr))
The SQLite version is more complex, as there's no one stop solution for truncating:
_modifiers = {
'year': ('start of year',),
'month': ('start of month',),
# This does not account for locale specific first day of week. 1 day
# is added so that the 1st day of week won't truncate to previous week.
# Replace 'weekday 0' with 'weekday 1', if you'd like first day of
# week to be Monday (in accordance with ISO 8601)
'week': ('1 day', 'weekday 0', '-7 days', 'start of day'),
'day': ('start of day',),
}
@compiles(Trunc, 'sqlite')
def compile_trunc_sqlite(element, compiler, **kw):
precision = element.precision
expr = element.expr
modifiers = _modifiers.get(precision)
if modifiers:
return compiler.process(func.datetime(expr, *modifiers))
elif precision == 'hour':
return compiler.process(func.datetime(
expr,
func.strftime('-%M minutes', expr),
func.strftime('-%f seconds', expr)))
elif precision == 'minute':
return compiler.process(func.datetime(
expr, func.strftime('-%f seconds', expr)))
elif precision == 'second':
return compiler.process(func.datetime(
expr,
func.strftime('-%f seconds', expr),
func.strftime('%S seconds', expr)))
The SQLite version does not support all the precision modifiers available in Postgresql, such as "quarter", but should be fairly useful. Usage:
In [16]: for p in ['year', 'month', 'week', 'day', 'hour', 'minute', 'second']:
...: print(engine.execute(select([Trunc(p, func.current_timestamp())])).scalar())
...:
2018-01-01 00:00:00
2018-08-01 00:00:00
2018-07-29 00:00:00
2018-08-03 00:00:00
2018-08-03 06:00:00
2018-08-03 06:18:00
2018-08-03 06:18:18
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.