Вычислите количество часов, проведенных пользователем за день

У меня есть таблица Clocking в базе данных. Я хочу подсчитать время, проведенное пользователями за день.

Например 2024-03-21, пользователь 1 тратит 6.8 hours, на следующий день он тратит n количество часов и так далее (['6.8', 'n', ... 'n'])

user date timein timeout
1 2024-03-21 10:42 AM 12:00 PM
1 2024-03-21 01:10 PM 06:00 PM
1 2024-03-22 01:00 PM 05:47 PM
... ... ... ...

Это мой models.py

class Clocking(models.Model):
    user = models.ForeignKey('User', models.DO_NOTHING)
    timein = models.CharField(max_length=15, blank=True, null=True)
    timeout = models.CharField(max_length=15, blank=True, null=True)
    date = models.DateField(null=False)

Я хотел получить список часов, проведенных в день, что было бы очень полезно для меня при построении графиков.

если вы хотите получить время, проведенное пользователем, вы можете выбрать все записи за одну дату, затем суммировать всех пользователей (timein - timeout), для этого вы можете преобразовать Charfield в объект datetime с помощью встроенной библиотеки, или лучше всего изменить тип поля вашей базы данных на DateTimeField или TimeField.

Пожалуйста, не используйте CharField для отслеживания. Представьте, что человек вводит now, как это будет работать? Это означает, что вы увеличите количество возможных значений, а также увеличите использование дискового пространства, хотя последнее, вероятно, не так уж и важно.

По сути, есть два варианта: работать с TimeFields:

from django.conf import settings


class Clocking(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING)
    date = models.DateField()
    timein = models.TimeField()
    timeout = models.TimeField(null=True)

или работать с двумя DateTimeField:

from django.conf import settings


class Clocking(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.DO_NOTHING)
    timein = models.DateTimeField()
    timeout = models.DateTimeField(null=True)

Второй вариант имеет три преимущества: (1) он также легко позволяет правильно регистрировать время в те дни, когда происходит переход на летнее время. Хотя оно обычно меняется в воскресенье около 2:00 AM, чтобы свести к минимуму количество проблем с бухгалтерией, все же возможно, что это произойдет, например, если человек работает в другом часовом поясе в это время; (2) оно также позволяет легко иметь несколько Clocking в одну и ту же дату, без дополнительной бухгалтерии; и (3) наконец, оно также означает, что мы можем иметь Clocking, который проходит за полночь. Действительно, представьте себе человека, который приходит в 9:00 вечера и уходит в 01:00 утра следующего дня, тогда в старой модели это будет проблематично, потребуется сначала проверить, не наступило ли время окончания раньше времени начала.

С помощью этого мы можем генерировать статистику для даты начала работы с элементом:

# second model
from django.db.models import F, Sum
from django.db.models.functions import TruncDate

Clocking.objects.filter(timeout__isnull=False).values(
    date=TruncDate('timein')
).annotate(total=Sum(F('timeout') - F('timein'))).order_by('date')

Note: Specifying null=False [Django-doc] is not necessary: fields are by default not NULLable.


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

Вернуться на верх