简体   繁体   中英

Django expression DateTime and Integer seconds

I want to annotate the difference between a DateTime and an Integer (seconds) on a legacy MySQL DB (so there is no chance to change the IntegerField to a DurationField) with Django 1.11

Report(Model):
    # time the report was sent
    time = DateTimeField()
    # seconds since the last reboot
    uptime = IntegerField()

MyModel.objects.all().annotate(
    last_report=Max(time),
    last_reboot=ExpressionWrapper(F('last_report') - F('uptime')), output_field=DateTimeField())
)

This would work, if uptime was a DurationField(), but won't work with an integer. So I tried converting the seconds to a timedelta

last_reboot=ExpressionWrapper(
    F('last_report') - F(timezone.timedelta(seconds=1)*F('uptime')),
    output_field=DateTimeField()
)

which gives me

AttributeError at ...

'CombinedExpression' object has no attribute 'split'

Is there a way to calculate with a DateTimeField() and a IntegerField() in a query expression?

I found a solution: Convert the integer to a duration using the ExpressionWrapper . As I am getting seconds and a DurationField() is Microseconds, I have to multiply them by 1,000,000.

last_reboot=ExpressionWrapper(
    F('last_report') - ExpressionWrapper(
        F('uptime') * 1000000,
        output_field=DurationField()
    ),
    output_field=DateTimeField()
)

Previously, I did something like below...might be useful for others.

.annotate(timestamp=RawSQL('DATE(milisecond_datetimestamp, \'unixepoch\')',[])) 

and another query where I had to convert the date integer field to hour

.annotate(hour=Round(F('milisecond_datetimestamp') % (3600 * 24) /3600)) 

and for Round you have to define SQL function like below

class Round(Func):
    function= 'ROUND'

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM