Forum Archive

Timestamp and keeping track of time

resserone13

I have the class method bed_start_time() and bed_end_time(). I would like the to keep track of when a room has been started being cleaned and the current time. I would also like to keep track of the time the room is finished being cleaned with bed_end_time(). I have it so the class method keeps track of the room number and the start time in a dict. I have another dict that keeps track of the end time. When I print the start and end time dict they show the same time for start and end even though they have been called at different time. Can someone help. I recently tried adding self to the method but I did not help.

room_with_stimes_dict = {}
room_with_etimes_dict = {}
room_start_times_dict = {}

class Room (object):
        def __init__ (self, room_num = None, assigned_house_keeper = None, room_start_time = None, room_end_time = None, room_start_cleaning = None, iso_type = None, running_time = None, assigned_nurse = None, assigned_patient = None):
                self.room_num = room_num
                self.assigned_house_keeper = assigned_house_keeper
                self.room_start_time = room_start_time
                self.room_end_time = room_end_time
                self.iso_type = iso_type
                self.running_time = running_time
                self.assigned_nurse = assigned_nurse
                self.assigned_patient = assigned_patient

        def __str__(self):
                return f'Room: {self.room_num} \nAssigned Nurse: {self.assigned_nurse} \nIso Type: {self.iso_type}'

        def room_start_time(self):
                room_start_time = datetime.datetime.now()
                room_start_times_dict [self.room_num] = room_start_time.strftime('%H:%M')
                return bed_start_time

        def bed_start_time(self):
                self.bed_start_time = datetime.datetime.now()
                room_with_stimes_dict [self.room_num] = self.bed_start_time.strftime('%H:%M')
                return self.bed_start_time

        def bed_end_time(self):
                self.bed_end_time = datetime.datetime.now()
                room_with_etimes_dict [self.room_num] = self.bed_end_time.strftime('%H:%M') 
                return self.bed_end_time        

        def add_room(self):
                pass    

#list of dirty rooms
dirty_rooms = [430, 6218, 520, 452, 444, 423,660,123,877,223,254,220,659,315,550,5228]

room_1 = Room()
room_1.room_num = 430
room_1.iso_type = 'COVID'

room_2 = Room()
room_2.room_num = 6218
room_2.iso_type = 'None'

room_3 = Room()
room_3.room_num = 654
room_3.iso_type = 'influenza'

room_4 = Room()
room_4.room_num = 220
room_4.iso_type = 'None'

#room start time
start_t1 = room_1.bed_start_time()
#time delay
time.sleep(9)
#room end time
end_t1 = room_1.bed_end_time()

time.sleep(3)

start_t2 = room_2.bed_start_time()
time.sleep(12)
end_t2 = room_2.bed_end_time()

time.sleep(3)

start_t3 = room_3.bed_start_time()
time.sleep(7)
end_t3 = room_3.bed_end_time()

time.sleep(3)

start_t4 = room_4.bed_start_time()
time.sleep(1)
end_t4 = room_4.bed_end_time()

#amount of time taken to clean the room             
elapsed_t1 = end_t1 - start_t1
elapsed_t2 = end_t2 - start_t2
elapsed_t3 = end_t3 - start_t3
elapsed_t4 = end_t4 - start_t4

#total time to clean all rooms
total_time = elapsed_t1 + elapsed_t2 + elapsed_t3 + elapsed_t4

#avg time to clean a room
avg_time = total_time / 4

#unsorted list of times
times = [elapsed_t1, elapsed_t2, elapsed_t3, elapsed_t4]

#sorted list by length of time. longest time is first                               
sorted_times = sorted(times, reverse=True)

#prints sorted list
print(sorted_times,'\n')

#test code              
print('Elapsed Time 1:')
print(elapsed_t1,'\n')
print('Elapsed Time 2:')
print(elapsed_t2,'\n')
print('Elapsed Time 3:')
print(elapsed_t3,'\n')
print('Total Time:')
print(total_time,'\n')
print('Avg Time:')
print(avg_time,'\n')
print('Room # and  Start Times')
print(room_with_stimes_dict, '\n')
print('Room # and End Times')
print(room_with_etimes_dict)
ccc

When posting code to this forum, please do three backticks on a line, then your code on the next line, then on the next line three backticks.

```
Your code...
```

cvp

You have even a button for this

resserone13

room_with_stimes_dict = {}
room_with_etimes_dict = {}
room_start_times_dict = {}

class Room (object):
        def __init__ (self, room_num = None, assigned_house_keeper = None, room_start_time = None, room_end_time = None, room_start_cleaning = None, iso_type = None, running_time = None, assigned_nurse = None, assigned_patient = None):
                self.room_num = room_num
                self.assigned_house_keeper = assigned_house_keeper
                self.room_start_time = room_start_time
                self.room_end_time = room_end_time
                self.iso_type = iso_type
                self.running_time = running_time
                self.assigned_nurse = assigned_nurse
                self.assigned_patient = assigned_patient
                room_with_stimes_dict = {}
                room_with_etimes_dict = {}
                room_start_times_dict = {}

        def __str__(self):
                return f'Room: {self.room_num} \nAssigned Nurse: {self.assigned_nurse} \nIso Type: {self.iso_type}'

        def room_start_time(self):
                room_start_time = datetime.datetime.now()
                room_start_times_dict [self.room_num] = room_start_time.strftime('%H:%M')
                return bed_start_time

        def bed_start_time(self):
                self.bed_start_time = datetime.datetime.now()
                room_with_stimes_dict [self.room_num] = self.bed_start_time.strftime('%H:%M')
                return self.bed_start_time

        def bed_end_time(self):
                self.bed_end_time = datetime.datetime.now()
                room_with_etimes_dict [self.room_num] = self.bed_end_time.strftime('%H:%M') 
                return self.bed_end_time        

        def add_room(self):
                pass    

#list of dirty rooms
dirty_rooms = [430, 6218, 520, 452, 444, 423,660,123,877,223,254,220,659,315,550,5228]

room_1 = Room()
room_1.room_num = 430
room_1.iso_type = 'COVID'

room_2 = Room()
room_2.room_num = 6218
room_2.iso_type = 'None'

room_3 = Room()
room_3.room_num = 654
room_3.iso_type = 'influenza'

room_4 = Room()
room_4.room_num = 220
room_4.iso_type = 'None'

#room start time
start_t1 = room_1.bed_start_time()
#time delay
time.sleep(9)
#room end time
end_t1 = room_1.bed_end_time()

time.sleep(3)

start_t2 = room_2.bed_start_time()
time.sleep(12)
end_t2 = room_2.bed_end_time()

time.sleep(3)

start_t3 = room_3.bed_start_time()
time.sleep(7)
end_t3 = room_3.bed_end_time()

time.sleep(3)

start_t4 = room_4.bed_start_time()
time.sleep(1)
end_t4 = room_4.bed_end_time()

#amount of time taken to clean the room             
elapsed_t1 = end_t1 - start_t1
elapsed_t2 = end_t2 - start_t2
elapsed_t3 = end_t3 - start_t3
elapsed_t4 = end_t4 - start_t4

#total time to clean all rooms
total_time = elapsed_t1 + elapsed_t2 + elapsed_t3 + elapsed_t4

#avg time to clean a room
avg_time = total_time / 4

#unsorted list of times
times = [elapsed_t1, elapsed_t2, elapsed_t3, elapsed_t4]

#sorted list by length of time. longest time is first                               
sorted_times = sorted(times, reverse=True)

#prints sorted list
print(sorted_times,'\n')

#test code              
print('Elapsed Time 1:')
print(elapsed_t1,'\n')
print('Elapsed Time 2:')
print(elapsed_t2,'\n')
print('Elapsed Time 3:')
print(elapsed_t3,'\n')
print('Total Time:')
print(total_time,'\n')
print('Avg Time:')
print(avg_time,'\n')
print('Room # and  Start Times')
print(room_with_stimes_dict, '\n')
print('Room # and End Times')
print(room_with_etimes_dict)

resserone13

@ccc @cvp I updated the post thanks for sharing the proper way to post code.

JonB
strftime('%H:%M')

You are storing in your global dicts only to the nearest minute. But your sleeps are a few seconds!

It is a really bad idea to have both an instance attribute, and an instance method with the same name.... because methods are attributes, so your init code is not doing what you think it is.

I'm honestly surprised this even runs, because it would seem you are overriding your various time methods with None inside your init method.

You also have some issues with missing"self" in a at least one method... Does this code actually run without error?

mikael

@resserone13, started thinking what this would look like in ”modern Python”, using data classes that came in 3.7 but need to be installed in Pythonista (Python 3.6) via stash.

Here’s a quick sketch that uses naive datetimes and does not cover per-bed times, among other failings:

from datetime import datetime, timedelta
from typing import List

from dataclasses import dataclass, field, asdict


log_time_resolution = 60  # or 1 minute 

@dataclass(unsafe_hash=True)
class Bed:
    number: int


@dataclass(unsafe_hash=True)
class HouseKeeper:
    name: str


@dataclass
class Room:    
    number: int
    assigned: HouseKeeper
    beds: List[Bed] = field(
        default_factory=lambda: [
            Bed(i) for i in range(1, 4+1)
        ])

    def __hash__(self):
        return self.number


@dataclass
class Cleaning:
    room: Room
    housekeeper: HouseKeeper
    start_time: datetime = None
    end_time: datetime = None

    def end(self, end_time=None):
        self.end_time = end_time or datetime.now()

    @property   
    def started(self):
        return bool(self.start_time)

    @property
    def completed(self):
        return bool(self.start_time and self.end_time)

    @property
    def duration(self):
        return (self.end_time - self.start_time) if self.completed else None

    def match(self, **kwargs):
        query = set(kwargs.items())
        content = set(self.__dict__.items())
        return query.issubset(content)


class CleaningLog(list):

    def start_cleaning(self, room, housekeeper=None, start_time=None):
        housekeeper = housekeeper or room.assigned
        cleaning = Cleaning(
            room=room,
            housekeeper=housekeeper,
            start_time=start_time or datetime.now(),
        )
        self.append(cleaning)
        return cleaning

    def total_time(self, **kwargs):
        seconds = sum([
            cleaning.duration
            for cleaning in self
            if cleaning.completed and
            cleaning.match(**kwargs)
        ], timedelta()).seconds
        return timedelta(seconds=round(seconds, log_time_resolution))

if __name__ == '__main__':

    # Usage example

    import faker
    fake = faker.Faker()

    # 5 rooms with different housekeepers
    rooms = [
        Room(number=i, assigned=HouseKeeper(name=fake.name()))
        for i in range(1, 5+1)
    ]
    first_room, second_room = rooms[:2]

    log = CleaningLog()

    # First cleaning by the assigned housekeeper
    # (Providing a time to simulate time passing)
    cleaning = log.start_cleaning(first_room)
    cleaning.end(datetime.now() + timedelta(minutes=10))

    # Second cleaning by another housekeeper
    cleaning2 = log.start_cleaning(
        first_room,
        housekeeper=second_room.assigned,
        start_time=datetime.now() + timedelta(minutes=15),
    )
    cleaning2.end(datetime.now() + timedelta(minutes=30))

    # Get the total cleaning time of the first room:

    print(
        f'Total for Room {first_room.number}:',
        log.total_time(room=first_room)
    )

    # Or first room by the assigned housekeeper:

    total_time = log.total_time(
        room=first_room,
        housekeeper=first_room.assigned,
    )
    print(
        f'Total for {first_room.assigned.name}:',
        total_time       
    )
resserone13

@JonB your right. It was the strftime(). I’m only keeping track of minutes and my test code is only seconds. The code output looks like this.

[datetime.timedelta(0, 12, 2110), datetime.timedelta(0, 9, 5850), datetime.timedelta(0, 7, 1252), datetime.timedelta(0, 1, 2087)]

Elapsed Time 1:
0:00:09.005850

Elapsed Time 2:
0:00:12.002110

Elapsed Time 3:
0:00:07.001252

Total Time:
0:00:29.011299

Avg Time:
0:00:07.252825

Room # and Start Times
{430: '12:56:42', 6218: '12:56:54', 654: '12:57:09', 220: '12:57:19'}

Room # and End Times
{430: '12:56:51', 6218: '12:57:06', 654: '12:57:16', 220: '12:57:20'}
Room: 430
Assigned Nurse: None
Iso Type: COVID

resserone13

@mikael thanks for the response. I’m going to review this and learn. I’m sure you can tell I’m just starting out. I write my code with Pythonista on my iPhone 11. Your code looks completely different then mine.

mikael

@resserone13, I know that it is a very different approach and I am sorry for that, since it does not necessarily help you progress with yours. I tried to think what I would recommend for your code, and found I had to define a potential data model for myself first.

If there is something there that you can reuse, great. And please ask if I can clarify how something works or – even better – why I chose to do something in a specific way.

If it helps, I have also used Pythonista almost exclusively on my iPhone for years now. Of course the typing can be clumsy, but nothing prevents you from incrementally building something significant.

resserone13

@mikael @mikael for sure. I been reviewing your code and I have picked up a few things. Like I have no Boolean test in my code and nothing really checking things. I also watched a video on data class and understand a bit more of why use chose them and why there is less code.

Why did you put end_time = end_time or datetime.now()

I’m guessing it so that end_time at least have a value of NONE.

And is this to check to se if the cleaning was started

    @property   
    def started(self):
        return bool(self.start_time)

ccc

I really like https://docs.python.org/3/library/doctest.html and we insist on them in submissions to https://github.com/TheAlgorithms/Python It allows us to run 700 pytests every time someone contributes code. Doctests really helps our contributors focus on quality and on finding corner cases in their code.

resserone13

@ccc @ccc a lot of good code here. Thank you. Bunch of sorting algorithms among other things. Thanks for this information.

mikael

Why did you put end_time = end_time or datetime.now()

It works together with having the end_time=None default in the method signature. If the method is not given an end_time, it is None, and then it gets the value of datetime.now().

It is essentially a 1-line version of:

if not end_time:
    end_time = datetime.now()

You can also use and in a similar way, but with a different meaning. E.g.:

some_value = obj and obj.attribute

I.e., if obj is None, obj.attribute will not get called (which would raise an exception), and some_value gets assigned the None.

This is again a more concise version of:

some_value = obj
if obj:
    some_value = obj.attribute

... or the much uglier (to me):

some_value = obj.attribute if obj else obj

And is this to check to se if the cleaning was started
@property def started(self): return bool(self.start_time)

Yes, but it is not really used in this code, and not very useful either, because the main way to get a cleaning object is with the start_cleaning method, so it is always at least started when you have it.

westjensontexas

Thanks for the clarification. .