Skip to content

Time

Manages the partition of time throughout the day.

Handles the time in the simulation.

This module contains the Timer class, which manages the advancement of time by the Simulator class.

Timer

Class desinged to manage how time is measured and advanced in the simulation.

In particular, it controls the size of timesteps and the type of timestep (morning, workday, evening, night, weekday, weekend, special holiday, etc).

Source code in june/time.py
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
class Timer:
    """Class desinged to manage how time is measured and advanced in the simulation.

    In particular, it controls the size of timesteps and the type of timestep (morning, workday, evening, night, weekday, weekend, special holiday, etc).

    """
    def __init__(
        self,
        initial_day: str = "2020-03-01 9:00",
        total_days: int = 10,
        weekday_step_duration: List[int] = (12, 12),
        weekend_step_duration: List[int] = (24,),
        weekday_activities: List[List[str]] = (
            ("primary_activity", "residence"),
            ("residence",),
        ),
        weekend_activities: List[List[str]] = (("residence",),),
        day_types: dict = None,
    ):

        day_i = datetime.datetime(
            *[int(value) for value in initial_day.split(" ")[0].split("-")]
        )
        hour_i = 0
        if len(initial_day.split(" ")) > 1:
            hour_i = int(initial_day.split(" ")[1].split(":")[0])
        self.initial_date = day_i + datetime.timedelta(hours=hour_i)

        if day_types is None:
            self.day_types = {
                "weekday": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
                "weekend": ["Saturday", "Sunday"],
            }
        else:
            self.day_types = day_types

        self.total_days = total_days
        self.weekday_step_duration = weekday_step_duration
        self.weekend_step_duration = weekend_step_duration
        self.weekday_activities = weekday_activities
        self.weekend_activities = weekend_activities

        self.previous_date = self.initial_date
        self.final_date = (
            self.initial_date
            + datetime.timedelta(days=total_days)
            # + datetime.timedelta(hours=24 - hour_i)
        )
        self.date = self.initial_date
        self.shift = 0
        self.delta_time = datetime.timedelta(hours=self.shift_duration)

    @classmethod
    def from_file(cls, config_filename):
        """Create a Timer object from a configuration.yaml file.

        This method is how the Timer object is created in the example scripts. It is created from a default example configuration file.

        Args:
            config_filename (str):
                Filename of the configuration.yaml file.
                Config file contains information such as the number of days to simulate for,
                the different sizes and types of timesteps (weekday, weekend, morning, evening, worktime, etc)

        """
        with open(config_filename) as f:
            config = yaml.load(f, Loader=yaml.FullLoader)
        time_config = config["time"]
        if "weekday" in config.keys() and "weekend" in config.keys():
            day_types = {"weekday": config["weekday"], "weekend": config["weekend"]}
        else:
            day_types = None


        timer = cls(
            initial_day=time_config["initial_day"],
            total_days=time_config["total_days"],
            weekday_step_duration=time_config["step_duration"]["weekday"],
            weekend_step_duration=time_config["step_duration"]["weekend"],
            weekday_activities=time_config["step_activities"]["weekday"],
            weekend_activities=time_config["step_activities"]["weekend"],
            day_types=day_types,
        )

        return timer

    @property
    def is_weekend(self):
        """ """
        if self.day_of_week in self.day_types["weekend"]:
            return True
        else:
            return False

    @property
    def day_type(self):
        """ """
        if self.day_of_week in self.day_types["weekend"]:
            return "weekend"
        else:
            return "weekday"

    @property
    def now(self):
        """ """
        difference = self.date - self.initial_date
        return difference.total_seconds() / SECONDS_PER_DAY

    @property
    def date_str(self):
        """ """
        return self.date.date().strftime("%Y-%m-%d")

    @property
    def duration(self):
        """ """
        return self.delta_time.total_seconds() / SECONDS_PER_DAY

    @property
    def day(self):
        """ """
        return int(self.now)

    @property
    def day_of_week(self):
        """ """
        return calendar.day_name[self.date.weekday()]

    @property
    def activities(self):
        """ """
        type_day = "weekend" if self.is_weekend else "weekday"
        return getattr(self, type_day + "_activities")[self.shift]


    @property
    def shift_duration(self):
        """ """
        type_day = "weekend" if self.is_weekend else "weekday"
        return getattr(self, type_day + "_step_duration")[self.shift]

    def reset(self):
        """ """
        self.date = self.initial_date
        self.shift = 0
        self.delta_time = datetime.timedelta(hours=self.shift_duration)
        self.previous_date = self.initial_date

    def reset_to_new_date(self, date):
        """

        Args:
            date: 

        """
        self.date = date
        self.shift = 0
        self.delta_time = datetime.timedelta(hours=self.shift_duration)
        self.previous_date = self.initial_date

    def is_first_timestep_of_day(self):
        """Check if this is the first timestep of the day"""
        return self.shift == 0

    def is_end_of_day(self):
        """Check if next timestep will be a new day"""
        current_date = self.date
        next_step_date = current_date + datetime.timedelta(hours=self.shift_duration)
        return current_date.day != next_step_date.day

    def __next__(self):
        self.previous_date = self.date
        self.date += self.delta_time
        self.shift += 1
        if self.previous_date.day != self.date.day:
            self.shift = 0
        self.delta_time = datetime.timedelta(hours=self.shift_duration)
        return self.date 

activities property

date_str property

day property

day_of_week property

day_type property

duration property

is_weekend property

now property

shift_duration property

from_file(config_filename) classmethod

Create a Timer object from a configuration.yaml file.

This method is how the Timer object is created in the example scripts. It is created from a default example configuration file.

Parameters:

Name Type Description Default
config_filename str

Filename of the configuration.yaml file. Config file contains information such as the number of days to simulate for, the different sizes and types of timesteps (weekday, weekend, morning, evening, worktime, etc)

required
Source code in june/time.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
@classmethod
def from_file(cls, config_filename):
    """Create a Timer object from a configuration.yaml file.

    This method is how the Timer object is created in the example scripts. It is created from a default example configuration file.

    Args:
        config_filename (str):
            Filename of the configuration.yaml file.
            Config file contains information such as the number of days to simulate for,
            the different sizes and types of timesteps (weekday, weekend, morning, evening, worktime, etc)

    """
    with open(config_filename) as f:
        config = yaml.load(f, Loader=yaml.FullLoader)
    time_config = config["time"]
    if "weekday" in config.keys() and "weekend" in config.keys():
        day_types = {"weekday": config["weekday"], "weekend": config["weekend"]}
    else:
        day_types = None


    timer = cls(
        initial_day=time_config["initial_day"],
        total_days=time_config["total_days"],
        weekday_step_duration=time_config["step_duration"]["weekday"],
        weekend_step_duration=time_config["step_duration"]["weekend"],
        weekday_activities=time_config["step_activities"]["weekday"],
        weekend_activities=time_config["step_activities"]["weekend"],
        day_types=day_types,
    )

    return timer

is_end_of_day()

Check if next timestep will be a new day

Source code in june/time.py
178
179
180
181
182
def is_end_of_day(self):
    """Check if next timestep will be a new day"""
    current_date = self.date
    next_step_date = current_date + datetime.timedelta(hours=self.shift_duration)
    return current_date.day != next_step_date.day

is_first_timestep_of_day()

Check if this is the first timestep of the day

Source code in june/time.py
174
175
176
def is_first_timestep_of_day(self):
    """Check if this is the first timestep of the day"""
    return self.shift == 0

reset()

Source code in june/time.py
155
156
157
158
159
160
def reset(self):
    """ """
    self.date = self.initial_date
    self.shift = 0
    self.delta_time = datetime.timedelta(hours=self.shift_duration)
    self.previous_date = self.initial_date

reset_to_new_date(date)

Parameters:

Name Type Description Default
date
required
Source code in june/time.py
162
163
164
165
166
167
168
169
170
171
172
def reset_to_new_date(self, date):
    """

    Args:
        date: 

    """
    self.date = date
    self.shift = 0
    self.delta_time = datetime.timedelta(hours=self.shift_duration)
    self.previous_date = self.initial_date