Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

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

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

from builtins import object 

from datetime import datetime 

from datetime import timedelta 

 

__all__ = ["TimeHandler"] 

 

 

class TimeHandler(object): 

"""Keep track of simulation time information. 

 

This is a class tied to SOCS/Scheduler (OpSim). 

Its properties will be reevaluated in the future and this 

class may disappear. 

 

Attributes 

---------- 

_unix_start : datetime.datetime 

Holder for the start of the UNIX epoch 

initial_dt : datetime.datetime 

The date/time of the simulation start. 

current_dt : datetime.datetime 

The current simulation date/time. 

""" 

 

def __init__(self, initial_date): 

"""Initialize the class. 

 

Parameters 

---------- 

initial_date : str 

The inital date in the format of YYYY-MM-DD. 

""" 

self._unix_start = datetime(1970, 1, 1) 

self.initial_dt = datetime.strptime(initial_date, "%Y-%m-%d") 

self.current_dt = self.initial_dt 

 

def _time_difference(self, datetime1, datetime2=None): 

"""Calculate the difference in seconds between two times. 

 

This function calculates the difference in seconds between two given :class:`datetime` instances. If 

datetime2 is None, it is assumed to be UNIX epoch start. 

 

Parameters 

---------- 

datetime1 : datetime.datetime 

The first datetime instance. 

datetime2 : datetime.datetime 

The second datetime instance. 

 

Returns 

------- 

float 

The difference in seconds between the two datetime instances. 

""" 

if datetime2 is None: 

datetime2 = self._unix_start 

return (datetime1 - datetime2).total_seconds() 

 

@property 

def initial_timestamp(self): 

"""float: Return the UNIX timestamp for the initial date/time. 

""" 

return self._time_difference(self.initial_dt) 

 

@property 

def current_timestamp(self): 

"""float: Return the UNIX timestamp for the current date/time. 

""" 

return self._time_difference(self.current_dt) 

 

@property 

def current_midnight_timestamp(self): 

"""float: Return the UNIX timestamp of midnight for the current date. 

""" 

midnight_dt = datetime(self.current_dt.year, self.current_dt.month, self.current_dt.day) 

return self._time_difference(midnight_dt) 

 

@property 

def next_midnight_timestamp(self): 

"""float: Return the UNIX timestamp of midnight for the next day after current date. 

""" 

midnight_dt = datetime(self.current_dt.year, self.current_dt.month, self.current_dt.day) 

midnight_dt += timedelta(**{"days": 1}) 

return self._time_difference(midnight_dt) 

 

@property 

def time_since_start(self): 

"""float: The number of seconds since the start date. 

""" 

return self._time_difference(self.current_dt, self.initial_dt) 

 

def update_time(self, time_increment, time_units): 

"""Update the currently held timestamp. 

 

This function updates the currently held time with the given increment and corresponding 

units. 

 

Parameters 

---------- 

time_increment : float 

The increment to adjust the current time. 

time_units : str 

The time unit for the increment value. 

""" 

time_delta_dict = {time_units: time_increment} 

self.current_dt += timedelta(**time_delta_dict) 

 

@property 

def current_timestring(self): 

"""str: Return the ISO-8601 representation of the current date/time. 

""" 

return self.current_dt.isoformat() 

 

def has_time_elapsed(self, time_span): 

"""Return a boolean determining if the time span has elapsed. 

 

This function looks to see if the time elapsed (current_time - initial_time) in units of 

seconds is greater or less than the requested time span. It will return true if the time span 

is greater than or equal the elapsed time and false if less than the elapsed time. 

 

Parameters 

---------- 

time_span : float 

The requested time span in seconds. 

 

Returns 

------- 

bool 

True if the time elapsed is greater or False if less than the time span. 

""" 

return time_span >= self._time_difference(self.current_dt, self.initial_dt) 

 

def future_datetime(self, time_increment, time_units, timestamp=None): 

"""Return a future datetime object. 

 

This function adds the requested time increment to the current date/time to get a future date/time 

and returns a datetime object. An alternative timestamp can be supplied and the time increment will 

be applied to that instead. This function does not update the internal timestamp. 

 

Parameters 

---------- 

time_increment : float 

The increment to adjust the current time. 

time_units : str 

The time unit for the increment value. 

timestamp : float, optional 

An alternative timestamp to apply the time increment to. 

 

Returns 

------- 

datetime.datetime 

The datetime object for the future date/time. 

""" 

if timestamp is not None: 

dt = datetime.utcfromtimestamp(timestamp) 

else: 

dt = self.current_dt 

time_delta_dict = {time_units: time_increment} 

return dt + timedelta(**time_delta_dict) 

 

def future_timestamp(self, time_increment, time_units, timestamp=None): 

"""Return the UNIX timestamp for the future date/time. 

 

This function adds the requested time increment to the current date/time to get a future date/time 

and returns the UNIX timestamp for that date/time. It does not update the internal timestamp. 

 

Parameters 

---------- 

time_increment : float 

The increment to adjust the current time. 

time_units : str 

The time unit for the increment value. 

timestamp : float, optional 

An alternative timestamp to apply the time increment to. 

 

Returns 

------- 

float 

The future UNIX timestamp. 

""" 

return self._time_difference(self.future_datetime(time_increment, time_units, timestamp=timestamp)) 

 

def future_timestring(self, time_increment, time_units, timestamp=None): 

"""Return the ISO-8601 representation of the future date/time. 

 

This function adds the requested time increment to the current date/time to get a future date/time 

and returns the ISO-8601 formatted string for that date/time. It does not update the internal 

timestamp. 

 

Parameters 

---------- 

time_increment : float 

The increment to adjust the current time. 

time_units : str 

The time unit for the increment value. 

timestamp : float, optional 

An alternative timestamp to apply the time increment to. 

 

Returns 

------- 

str 

The future date/time in ISO-8601. 

""" 

return self.future_datetime(time_increment, time_units, timestamp=timestamp).isoformat() 

 

def time_since_given(self, timestamp): 

"""Return the elapsed time (seconds). 

 

This function takes the given timestamp and calculates the elapsed time in seconds 

between it and the initial timestamp in the handler. 

 

Parameters 

---------- 

timestamp : float 

A UNIX timestamp 

 

Returns 

------- 

float 

The elapsed time (seconds) between the given 

""" 

dt = datetime.utcfromtimestamp(timestamp) 

return self._time_difference(dt, self.initial_dt) 

 

def time_since_given_datetime(self, given_datetime, reverse=False): 

"""Return the elapsed time (seconds). 

 

This function takes a given datetime object and calculates the elapsed time in seconds 

between it and the initial timestamp in the handler. If the given datetime is prior to 

the initial timestamp in the handler, use the reverse flag. 

 

Parameters 

---------- 

given_datetime : datetime 

The given timestamp. 

reverse : bool, optional 

Flag to make the difference in reverse. Default is False. 

 

Returns 

------- 

float 

The elapsed time (seconds) between the given timestamp and the initial timestamp 

""" 

if reverse: 

return self._time_difference(self.initial_dt, given_datetime) 

else: 

return self._time_difference(given_datetime, self.initial_dt)