0
\$\begingroup\$

Is there any way to improve this code: punch:0 -> in punch:1 -> out

from datetime import datetime

attendance = [{"id": 1, "punch": 0, "date": "22-04-2022 02:10:00"},
          {"id": 1, "punch": 1, "date": "22-04-2022 03:00:00"},

          {"id": 1, "punch": 1, "date": "22-04-2022 04:00:00"},
          {"id": 1, "punch": 0, "date": "22-04-2022 05:00:00"},

          {"id": 1, "punch": 1, "date": "22-04-2022 06:00:00"},
          {"id": 1, "punch": 1, "date": "22-04-2022 08:00:10"},
          ]

sessions = []
total_hours = datetime.strptime("00:00:00", '%H:%M:%S')
in_time = None
out_time = None
for k in attendance:
if k["punch"].__eq__(0):
    in_time = k["date"]
elif k["punch"].__eq__(1):
    print(k)
    if in_time is not None:
        out_time = k["date"]
        total_hours += datetime.strptime(out_time, '%d-%m-%Y %H:%M:%S') - \
                           datetime.strptime(in_time, '%d-%m-%Y %H:%M:%S')
        sessions.append((in_time, out_time))
        in_time = None
print(sessions, total_hours.time())

output: [('22-04-2022 02:10:00', '22-04-2022 03:00:00'), ('22-04-2022 05:00:00', '22-04-2022 06:00:00')] 01:50:00

\$\endgroup\$
1
  • \$\begingroup\$ This appears to be a near-duplicate of this question with none of the advice followed and none of the answers accepted. What's your expectation here? \$\endgroup\$
    – Reinderien
    Apr 14, 2022 at 13:39

1 Answer 1

2
\$\begingroup\$

Declare the constants your program needs. This helps to document your code and reduce the chance of bugs:

from datetime import datetime, timedelta

PUNCH_IN = 0
PUNCH_OUT = 1
TIME_FORMAT = '%d-%m-%Y %H:%M:%S'

Organize the logic in well-focused functions. Avoid the temptation to do too many things at once. First handle the grouping of punches into start-end pairs. (Since it's a very simple operation, parsing the datetimes can be handled here as well, but if the situation were more complex, delegating the parsing to a separate function would make sense.)

def get_sessions(attendance):
    start = None
    for d in attendance:
        t = datetime.strptime(d['date'], TIME_FORMAT)
        p = d['punch']
        if p == PUNCH_IN:
            start = t
        elif start and p == PUNCH_OUT:
            yield (start, t)
            start = None

Compute the total. With the annoying part out of the way, computing the total is a straightforward sum of timedeltas.

def compute_total_time(sessions):
    return sum(
        (end - start for start, end in sessions),
        timedelta()
    )

def main():
    attendance = [ ... ]
    sessions = tuple(get_sessions(attendance))
    total = compute_total_time(sessions)
    print(total)

if __name__ == '__main__':
    main()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.