我是新手。先谢谢你了。
我正在做一个每日工作时间记录(DTR),计算每天的总工作时间,并显示上班时间和下班时间(AM)以及上班时间和下班时间(PM)。如果所有的超时和超时都发生在同一天,我已经可以显示超时和超时,并显示总工作时间,但我的问题是,当超时和超时跨越多天时,例如:
# If the attendance happened on the same day, I can compute the total duty hours, in this case, it is 8 hours (hours only)
[datetime.datetime(1900, 1, 1, 7, 51, 57), datetime.datetime(1900, 1, 1, 12, 0, 18), datetime.datetime(1900, 1, 1, 12, 19, 24), datetime.datetime(1900, 1, 1, 17, 0, 8)]
# But, if the time-in and time-out was on separate day, I was not able to compute the total duty hours.
[datetime.datetime(1900, 1, 1, 7, 57, 30)] # Time-in
[datetime.datetime(1900, 1, 1, 6, 5, 36)] # Time-out
# My initial plan to compute this, is to add an "end_time" and "start_time".
# Initially, I want the data to be like this.
# With this, I can compute each day by adding an "end_time" and "start_time"
# It is also desirable to indicate the computed total duty hours in the time-out day.
[datetime.datetime(1900, 1, 1, 7, 57, 30), datetime.datetime(1900, 1, 1, 23, 59, 59)]
[datetime.datetime(1900, 1, 1, 00, 00, 01), datetime.datetime(1900, 1, 1, 6, 5, 36)]
# With the custom_filter.py applied, the data looks like this.
# I was not able to insert the start date in the second line.
[datetime.datetime(1900, 1, 1, 7, 57, 30), datetime.datetime(1900, 1, 1, 23, 59, 59)]
[datetime.datetime(1900, 1, 1, 6, 5, 36), datetime.datetime(1900, 1, 1, 23, 59, 59)]
至于数据的格式,请参考我下面的代码。任何建议都是非常欢迎和赞赏。
dtr/model.py
from django.db import models
from django.utils.translation import gettext_lazy as _
class DailyAttendance(models.Model):
date = models.DateField(verbose_name=_('Date'))
profile = models.ForeignKey("employee_profile.PersonalInformation", related_name="daily_attendance_records", on_delete=models.CASCADE, verbose_name=_('Profile'), blank=True, null=True)
attendance_records = models.ManyToManyField("AttendanceRecord", related_name="daily_attendance_records", verbose_name=_('Attendance Records'), blank=True)
class Meta:
verbose_name_plural = "Daily Attendance Records"
def __str__(self):
return f"{self.profile} - {self.date}"
punch = [
('0', 'In'),
('1', 'Out'),
('2', 'Break-Out'),
('3', 'Break-In'),
('4', 'Overtime-In'),
('5', 'Overtime-Out'),
]
status = [
('1', 'Finger print'),
('4', 'Card'),
('15', 'Face recognition'),
]
class AttendanceRecord(models.Model):
profile = models.ForeignKey("employee_profile.PersonalInformation", related_name="attendance_records_profile", on_delete=models.CASCADE, verbose_name=_('Profile'), blank=True, null=True)
daily_attendance = models.ForeignKey("DailyAttendance", related_name="attendance_record_daily", on_delete=models.CASCADE, verbose_name=_('Daily Attendance'), blank=True, null=True)
uid = models.CharField(verbose_name=_('UID'), max_length=255, blank=True, null=True)
date = models.DateField(verbose_name=_('Date'), blank=True, null=True)
time = models.TimeField(verbose_name=_('Time'), blank=True, null=True)
punch = models.CharField(verbose_name=_('Punch'), max_length=255, choices=punch, blank=True, null=True)
status = models.CharField(verbose_name=_('Status'), max_length=255, choices=status, blank=True, null=True)
class Meta:
verbose_name_plural = "Attendance Records"
def __str__(self):
if self.punch == '0':
punch = 'In'
elif self.punch == '1':
punch = 'Out'
elif self.punch == '2':
punch = 'Break-Out'
elif self.punch == '3':
punch = 'Break-In'
elif self.punch == '4':
punch = 'Overtime-In'
elif self.punch == '5':
punch = 'Overtime-Out'
return f"{self.profile} - {self.date} - {punch} - {self.time}"
dtr/view.py
@login_required(login_url='/admin')
def dtr(request, profile):
try:
profile = PersonalInformation.objects.get(employee_no=profile)
except PersonalInformation.DoesNotExist:
profile = None
attendance_records = DailyAttendance.objects.filter(profile=profile)
date_time_data = {} # Initialize an empty dictionary to store date-time data
for day in range(1, 32): # Loop through days 01 to 31
day_str = str(day).zfill(2) # Convert day to a zero-padded string (e.g., "01", "02", ..., "31")
# Initialize an empty list for the day
date_time_data[day_str] = []
# Filter attendance_records for the current day
for daily_attendance in attendance_records:
if daily_attendance.date.strftime('%d') == day_str:
for record in daily_attendance.attendance_records.all():
time_obj = record.time.strftime('%H:%M:%S')
punch_obj = record.punch # Not in-use
date_time_data[day_str].append(time_obj) # Append the time to the list for the day
context = {
"title": "DTR",
"profile": profile,
"attendance_records": attendance_records,
"date_time_data": date_time_data,
}
return render(request, "dtr/dtr.html", context)
dtr/templatetags/custom_filters.py
from django import template
from datetime import datetime, timedelta
register = template.Library()
@register.filter(name='calculate_daily_duration')
def calculate_daily_duration(time_list):
total_duration = timedelta()
time_objects = [datetime.strptime(time_str, '%H:%M:%S') for time_str in time_list]
# This part is the issue and is the responsible to append or insert an end_time or start_time depending if the the attendance data has only one data.
# Start#
if len(time_objects) == 1:
time_str = time_objects[0].strftime('%H:%M:%S')
time_obj = datetime.strptime(time_str, '%H:%M:%S')
et = datetime.strptime('23:59:59', '%H:%M:%S')
st = datetime.strptime('00:00:01', '%H:%M:%S')
if time_obj.time() < et.time():
time_objects.append(et)
elif time_obj.time() > st.time():
time_objects.insert(0, st)
# End#
# This part computes the time data
for i in range(0, len(time_objects), 2):
if i + 1 < len(time_objects):
start_time = time_objects[i]
end_time = time_objects[i + 1]
duration = end_time - start_time
total_duration += duration
print(time_objects)
total_hours, remainder = divmod(total_duration.total_seconds(), 3600)
return f'{int(total_hours)}'
`dtr template (HTML)`
<div class="c x0 y30 wa ha">
<div class="t m0 x11 hb ye ff2 fs3 fc0 sc0 ls0 ws0">28</div>
</div>
<div class="c xc y30 wb ha">
<div class="t m0 x6 hb ye ff3 fs3 fc0 sc0 ls0 ws0">{% for daily_attendance in attendance_records %}{% if daily_attendance.date|date:"d" == "28" %}{% for record in daily_attendance.attendance_records.all %}{% if record.punch == "0" and record.time|time:"H:i" >= "00:00" and record.time|time:"H:i" <= "11:59" %}{{ record.time|time:"H:i" }}{% endif %}{% endfor %}{% endif %}{% endfor %}</div>
</div>
<div class="c x10 y30 wb ha">
<div class="t m0 x6 hb ye ff3 fs3 fc0 sc0 ls0 ws0">{% for daily_attendance in attendance_records %}{% if daily_attendance.date|date:"d" == "28" %}{% for record in daily_attendance.attendance_records.all %}{% if record.punch == "1" and record.time|time:"H:i" >= "00:00" and record.time|time:"H:i" < "12:59" %}{{ record.time|time:"H:i" }}{% endif %}{% endfor %}{% endif %}{% endfor %}</div>
</div>
<div class="c x5 y30 wb ha">
<div class="t m0 x6 hb ye ff3 fs3 fc0 sc0 ls0 ws0">{% for daily_attendance in attendance_records %}{% if daily_attendance.date|date:"d" == "28" %}{% for record in daily_attendance.attendance_records.all %}{% if record.punch == "0" and record.time|time:"H:i" >= "12:00" %}{{ record.time|time:"H:i" }}{% endif %}{% endfor %}{% endif %}{% endfor %}</div>
</div>
<div class="c x12 y30 wb ha">
<div class="t m0 x6 hb ye ff3 fs3 fc0 sc0 ls0 ws0">{% for daily_attendance in attendance_records %}{% if daily_attendance.date|date:"d" == "28" %}{% for record in daily_attendance.attendance_records.all %}{% if record.punch == "1" and record.time|time:"H:i" >= "13:00" and record.time|time:"H:i" <= "23:59" %}{{ record.time|time:"H:i" }}{% endif %}{% endfor %}{% endif %}{% endfor %}</div>
</div>
<div class="c xe y30 wc hf">
<div class="t m0 xd hb ye ff3 fs3 fc0 sc0 ls0 ws0">{% for day, time_list in date_time_data.items %}{% if day == "28" %}{{time_list|calculate_daily_duration}}{% endif %}{% endfor %}</div>
</div>
截图:
1条答案
按热度按时间ss2ws0br1#
幸运的是,我的问题解决了...这是解决问题的代码。注意:
custom_filter.py
已被删除。所有操作都在view.py
上。因为我是个新手,所以不能详细解释。这是整个
view.py
截图: