ES.timeslot
Created on Sun Jan 2 18:30:14 2022
@author: Philippe@loco-labs.io
The ES.timeslot
module contains the TimeSlot
and the TimeInterval
classes.
What is the TimeSlot Object ?
The TimeSlot Object is a representation of time intervals data and properties. For example, I can represent the working day of 2022-march-15 by a TimeSlot which includes the following intervals:
- from 9 a.m. to 12 p.m.
- from 2 p.m. to 4:30 p.m.
- from 5 p.m. to 7:30 p.m. i.e. a duration of 8 hours centered around 3 p.m. with bounds at 9 a.m. and 7:30 p.m.
Main principles
The main principles are as follows :
Data structure
A TimeSlot
is a list of TimeInterval
.
A TimeInterval
is defined by two datetime
objects (start and end)
Multiple properties are associated with the data :
- duration : sum of the lenght of each TimeInterval
- centroïd : instant assicited to the middle of the duration
- bounds : minimum, maximum and middle
- type : instant, interval or slot
Relationships and assembly
Two TimeSlot
can be compared with five statuses (equals, contains, whitin, disjoint, intersects).
Multiple operations between two objects can be performed :
1# -*- coding: utf-8 -*- 2""" 3Created on Sun Jan 2 18:30:14 2022 4 5@author: Philippe@loco-labs.io 6 7The `ES.timeslot` module contains the `TimeSlot` and the `TimeInterval` classes. 8 9# What is the TimeSlot Object ? 10 11The TimeSlot Object is a representation of time intervals data and properties. For example, 12 I can represent the working day of 2022-march-15 by a TimeSlot which includes the following intervals: 13- from 9 a.m. to 12 p.m. 14- from 2 p.m. to 4:30 p.m. 15- from 5 p.m. to 7:30 p.m. 16i.e. a duration of 8 hours centered around 3 p.m. with bounds at 9 a.m. and 7:30 p.m. 17 18# Main principles 19 20The main principles are as follows : 21 22<img src="./timeslot_data_structure.png" width="800"> 23 24## Data structure 25 26A `TimeSlot` is a list of `TimeInterval`. 27 28A `TimeInterval` is defined by two `datetime` objects (start and end) 29 30Multiple properties are associated with the data : 31 32- duration : sum of the lenght of each TimeInterval 33- centroïd : instant assicited to the middle of the duration 34- bounds : minimum, maximum and middle 35- type : instant, interval or slot 36 37## Relationships and assembly 38 39Two `TimeSlot` can be compared with five statuses (equals, contains, whitin, disjoint, intersects). 40 41Multiple operations between two objects can be performed : 42 43- union between two `TimeSlot` 44- intersection between two `TimeSlot` 45- complementing a `TimeSlot` in an interval 46 47""" 48import datetime 49import json, numpy, pandas, bson 50from ESconstante import ES #, _identity 51 52class TimeSlotEncoder(json.JSONEncoder): 53 """add a new json encoder for TimeSlot""" 54 def default(self, o) : 55 if isinstance(o, datetime.datetime) : return o.isoformat() 56 return json.JSONEncoder.default(self, o) 57 58class TimeSlot: 59 ''' 60 *Attributes (for @property see methods)* : 61 62 - **slot** : list of `TimeInterval` 63 64 The methods defined in this class are : 65 66 *dynamic value property (getters)* 67 68 - `TimeSlot.Bounds` 69 - `TimeSlot.bounds` 70 - `TimeSlot.Centroid` 71 - `TimeSlot.duration` 72 - `TimeSlot.instant` 73 - `TimeSlot.middle` 74 - `TimeSlot.interval` 75 - `TimeSlot.stype` 76 77 *instance methods* 78 79 - `TimeSlot.json` 80 - `TimeSlot.link` 81 - `TimeSlot.timetuple` 82 - `TimeSlot.union` 83 ''' 84 def __init__(self, val=None): 85 ''' 86 TimeSlot constructor. 87 88 *Parameters* 89 90 - **val** : date, interval, list of interval (default None) - with several formats 91 (tuple, list, string, datetime, TimeSlot, TimeInterval, numpy datetime64, pandas timestamp) 92 93 *Returns* : None''' 94 slot = [] 95 if isinstance(val, str): 96 try: val = json.loads(val) 97 except: 98 val = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 99 #try: val = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 100 #except: val = None 101 if val == None : 102 self.slot = slot 103 return 104 if isinstance(val, tuple): val = list(val) 105 if isinstance(val, list) and len(val) == 2 and not isinstance(val[0], TimeInterval): 106 try : slot.append(TimeInterval(val)) 107 except : 108 for interv in val : slot.append(TimeInterval(interv)) 109 elif isinstance(val, list): 110 try : 111 for interv in val : slot.append(TimeInterval(interv)) 112 except : slot.append(TimeInterval(val)) 113 elif isinstance(val, datetime.datetime): slot.append(TimeInterval(val)) 114 elif isinstance(val, TimeSlot): slot = val.slot 115 elif isinstance(val, TimeInterval): slot.append(val) 116 else : slot.append(TimeInterval(val)) 117 self.slot= TimeSlot._reduced(slot) 118 119 def __add__(self, other): 120 ''' Add other's values to self's values in a new TimeSlot''' 121 return TimeSlot(TimeSlot._reduced(self.slot + other.slot)) 122 123 def __iadd__(self, other): 124 ''' Add other's values to self's values''' 125 self.slot = self._reduced(self.slot + other.slot) 126 127 def __contains__(self, item): 128 ''' item of extval''' 129 return item in self.slot 130 131 def __getitem__(self, index): 132 ''' return interval item''' 133 return self.slot[index] 134 135 def __setitem__(self, index, interv): 136 ''' modify interval item''' 137 if index < 0 or index >= len(self) : raise TimeSlotError("out of bounds") 138 self.slot[index] = TimeInterval(interv) 139 self.slot= TimeSlot._reduced(self.slot) 140 141 def __len__(self): 142 '''return the number of intervals included''' 143 return len(self.slot) 144 145 #def __repr__(self): 146 def __str__(self): 147 ''' return the type of slot and the json representation''' 148 return self.stype + '\n' + self.json(encoded=True, encode_format='json') 149 150 def __repr__(self): 151 #return self.__class__.__name__ + f'({self.slot})' 152 return self.__class__.__name__ + '(' + self.json(encoded=True, encode_format='json') + ')' 153 154 def __eq__(self, other): 155 '''equal if the slots are equals''' 156 try: return self.slot == other.slot 157 except: return False 158 159 def __lt__(self, other): 160 '''compare the earliest dates''' 161 return self.slot[0] < other.slot[0] 162 163 def __hash__(self): 164 return sum(hash(interv) for interv in self.slot) 165 #return hash(self.json(True)) 166 167 @property 168 def Bounds(self): 169 '''return an interval TimeSlot with the bounds of the TimeSlot object''' 170 return TimeSlot(self.bounds) 171 172 @property 173 def bounds(self): 174 '''return a tuple with the start and end dates with isoformat string''' 175 return (TimeSlot.form(self.slot[0].start), TimeSlot.form(self.slot[len(self) - 1].end)) 176 177 @classmethod 178 def cast(cls, value): 179 ''' 180 tranform a value (unique or list) in a list of `TimeSlot` 181 182 *Parameters* 183 184 - **value** : value to transform 185 186 *Returns* 187 188 - **list** : list of `TimeSlot` 189 ''' 190 if isinstance(value, list): 191 try : 192 return [cls(val) for val in value] 193 except : 194 return [cls(value)] 195 else : return [cls(value)] 196 197 @property 198 def Centroid(self): 199 '''return a TimeSlot with the date corresponding to the middle of the duration''' 200 return TimeSlot(self.instant) 201 202 @property 203 def duration(self): 204 '''cumulative duration of each interval (timedelta format)''' 205 duration = datetime.timedelta() 206 for interv in self.slot : duration += interv.duration 207 return duration 208 209 @staticmethod 210 def form(dtime): 211 if dtime.timetuple()[3:6]==(0,0,0): return dtime.date().isoformat() 212 return dtime.isoformat() 213 214 @property 215 def instant(self): 216 '''return the date corresponding to the middle of the duration (datetime format)''' 217 duration = self.duration / 2 218 for interv in self.slot : 219 if duration > interv.duration : 220 duration -= interv.duration 221 else : 222 return interv.start + duration 223 224 @property 225 def middle(self): 226 '''return the date corresponding to the middle of the bounds (datetime format)''' 227 return self.bounds.instant 228 229 @property 230 def name(self): 231 ''' class name''' 232 return self.__class__.__name__ 233 234 @property 235 def interval(self): 236 '''return a list with the start and end dates (datetime format)''' 237 return [self.slot[0].start, self.slot[len(self) - 1].end] 238 239 @property 240 def stype(self): 241 '''return a string with the type of TimeSlot (instant, interval, slot)''' 242 if len(self.slot) == 1 : return self.slot[0].stype 243 else : return 'slot' 244 245 def json(self, **kwargs): 246 ''' 247 Return json/bson structure with the list of TimeInterval. 248 249 *Parameters* 250 251 - **encoded** : defaut False - if False return dict, else return json string/bson bytes 252 - **encode_format** : defaut 'json' - return json, bson or cbor format 253 254 *Returns* : string or dict''' 255 option = {'encoded' : False, 'encode_format' : 'json'} | kwargs 256 if len(self) == 1 : js = self.slot[0].json(encoded=False, encode_format=option['encode_format']) 257 else : js = [interv.json(encoded=False, encode_format=option['encode_format']) for interv in self.slot] 258 if option['encoded'] and option['encode_format'] == 'json': return json.dumps(js, cls=TimeSlotEncoder) 259 if option['encoded'] and option['encode_format'] == 'bson': return bson.encode(js) 260 return js 261 262 def link(self, other): 263 ''' 264 Return the status (string) of the link between two TimeSlot (self and other). 265 - equals : if self and other are the same 266 - disjoint : if self's intervals and other's intervals are all disjoint 267 - within : if all self's intervals are included in other's intervals 268 - contains : if all other's intervals are included in self's intervals 269 - intersects : in the others cases 270 271 *Parameters* 272 273 - **other** : TimeSlot to be compared 274 275 *Returns* 276 277 - **tuple** : (string(status), boolean(full or not))''' 278 if self.stype == 'instant' : point, oslot = self[0], other 279 elif other.stype == 'instant' : point, oslot = other[0], self 280 else : point = None 281 if point is not None : 282 contains = equals = False 283 for interv in oslot: 284 contains = contains or interv.link(point) == 'contains' 285 equals = equals or interv.link(point) == 'equals' 286 if equals and not contains : return ('equals', True) 287 if contains and point == other[0] : return ('contains', True) 288 if contains and point == self[0] : return ('within', True) 289 return ('disjoint', True) 290 else : 291 union = self + other 292 link = 'intersects' 293 full = True 294 if union.duration == self.duration == other.duration : 295 full = len(union) == len(self) == len(other) 296 link = 'equals' 297 elif union.duration == self.duration : 298 full = len(union) == len(self) 299 link = 'contains' 300 elif union.duration == other.duration : 301 full = len(union) == len(other) 302 link = 'within' 303 elif union.duration == self.duration + other.duration : 304 full = len(union) == len(self) + len(other) 305 link = 'disjoint' 306 return (link, full) 307 308 def timetuple(self, index=0, encoded=False): 309 ''' 310 Return json structure with the list of TimeInterval (timetuple filter). 311 312 *Parameters* 313 314 - **index** : integer, defaut 0 - timetuple format to apply : 315 - 0 : year 316 - 1 : month 317 - 2 : day 318 - 3 : hour 319 - 4 : minute 320 - 5 : seconds 321 - 6 : weekday 322 - 7 : yearday 323 - 8 : isdst (1 when daylight savings time is in effect, 0 when is not) 324 - **encoded** : defaut False - if True return string, else return dict 325 326 *Returns* : string or dict''' 327 if len(self) == 1 : js = self.slot[0].timetuple(index, False) 328 else : js = [interv.timetuple(index, False) for interv in self.slot] 329 if encoded : return json.dumps(js, cls=TimeSlotEncoder) 330 else : return js 331 332 def union(self, other): 333 ''' Add other's values to self's values in a new TimeSlot (same as __add__)''' 334 return self.__add__(other) 335 336 @staticmethod 337 def _reduced(listinterv): 338 ''' return an ordered and non-overlapping list of TimeInterval from any TimeInterval list''' 339 if not isinstance(listinterv, list) or len(listinterv) == 0 : return [] 340 union = [] 341 slot = sorted(listinterv) 342 interv = slot[0] 343 i = j = 0 344 while i < len(slot) : 345 for j in range(i + 1, len(slot)): 346 if interv.link(slot[j]) == 'within' : interv = slot[j] 347 elif interv.link(slot[j]) == 'intersects' : interv = interv.union(slot[j]) 348 elif interv.link(slot[j]) == 'disjoint' : 349 union.append(interv) 350 interv = slot[j] 351 i = j 352 break 353 if j >= len(slot) - 1 : 354 union.append(interv) 355 break 356 return union 357 358class TimeInterval: # !!! interval 359 ''' 360 *Attributes (for @property see methods)* : 361 362 - **start** : datetime Object - start of `TimeInterval` 363 - **end** : datetime Object - end of `TimeInterval` 364 365 The methods defined in this class are : 366 367 *dynamic value property (getters)* 368 369 - `TimeInterval.Bounds` 370 - `TimeInterval.bounds` 371 - `TimeInterval.Centroid` 372 - `TimeInterval.duration` 373 - `TimeInterval.instant` 374 - `TimeInterval.stype` 375 376 *instance methods* 377 378 - `TimeInterval.json` 379 - `TimeInterval.link` 380 - `TimeInterval.timetuple` 381 - `TimeInterval.union` 382 ''' 383 def __init__(self, val= ES.nullDate): 384 ''' 385 TimeInterval constructor. 386 387 *Parameters* 388 389 - **val** : date, interval (default ES.nullDate) - with several formats 390 (list, string, datetime, TimeInterval, numpy datetime64, pandas timestamp) 391 392 *Returns* : None''' 393 self.start = self.end = ES.nullDate 394 if isinstance(val, str): 395 try: 396 sl = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 397 if sl != None : self.start = self.end = sl 398 return 399 except: 400 try: val = json.loads(val) 401 except: val = ES.nullDate 402 if isinstance(val, list) : self._initInterval(val) 403 elif isinstance(val, TimeInterval) : self.start, self.end = val.start, val.end 404 else : 405 dat = self._initDat(val) 406 if dat != None : self.start = self.end = dat 407 408 #def __repr__(self): 409 def __str__(self): 410 ''' return the type of interval and the json representation''' 411 return self.stype + '\n' + self.json(encoded=True, encode_format='json') 412 413 def __repr__(self): 414 #if self.stype == 'instant' : return self.__class__.__name__ + f'("{self.start}")' 415 #return self.__class__.__name__ + f'(["{self.start}","{self.end}"])' 416 return self.__class__.__name__ + '(' + self.json(encoded=True, encode_format='json') + ')' 417 418 def __eq__(self, other): 419 '''equal if the 'start' and 'end' dates are equals''' 420 return self.start == other.start and self.end == other.end 421 422 def __lt__(self, other): 423 '''compare the earliest dates (start)''' 424 return self.start < other.start 425 426 def __hash__(self): 427 return hash(self.start) + hash(self.end) 428 #return hash(self.json(True)) 429 430 @property 431 def bounds(self): 432 '''return a tuple with the start and end dates with isoformat string''' 433 return (TimeSlot.form(self.start), TimeSlot.form(self.end)) 434 435 @property 436 def Centroid(self): 437 '''return a TimeInterval with the date corresponding to the middle of the interval''' 438 return TimeInterval(self.instant) 439 440 @property 441 def duration(self): 442 '''duration between 'end' and 'start' date (timedelta format)''' 443 return self.end - self.start 444 445 @property 446 def instant(self): 447 '''return the date corresponding to the middle of the duration (datetime format)''' 448 return self.start + (self.end - self.start) / 2 449 450 @property 451 def stype(self): 452 '''return a string with the type of TimeInterval (instant, interval)''' 453 if self.start == self.end : return 'instant' 454 return 'interval' 455 456 def json(self, encoded=False, encode_format='json'): 457 ''' 458 Return json/bson structure (date if 'instant' or [start, end] if 'interval') 459 with datetime or datetime.isoformat for dates. 460 461 *Parameters* 462 463 - **encoded** : defaut False - if True return dict, else return json string/bson bytes 464 - **encode_format** : defaut 'json' - return json, bson or cbor format 465 466 *Returns* : string or dict''' 467 if self.stype == 'instant': js = self.start 468 else: js = [self.start, self.end] 469 '''if self.stype == 'instant' : 470 if encode_format == 'bson': js = self.start 471 else: 472 js = TimeSlot.form(self.start) 473 elif self.stype == 'interval' : 474 if encode_format == 'bson': js = [self.start, self.end] 475 else: js = [TimeSlot.form(self.start), TimeSlot.form(self.end)]''' 476 if encoded and encode_format == 'json': return json.dumps(js, cls=TimeSlotEncoder) 477 if encoded and encode_format == 'bson': return bson.encode(js) 478 return js 479 480 def link(self, other): 481 ''' 482 Return the status (string) of the link between two TimeIntervals (self and other). 483 - equals : if self and other are the same 484 - disjoint : if self's interval and other's interval are disjoint 485 - within : if other's interval is included in self's interval 486 - contains : if self's interval is included in other's interval 487 - intersects : in the others cases 488 489 *Parameters* 490 491 - **other** : TimeInterval to be compared 492 493 *Returns* : string''' 494 if self.start == other.start and self.end == other.end : return 'equals' 495 if self.start <= other.start and self.end >= other.end : return 'contains' 496 if self.start >= other.start and self.end <= other.end : return 'within' 497 if self.start <= other.end and self.end >= other.start : return 'intersects' 498 return 'disjoint' 499 500 def timetuple(self, index=0, encoded=False): 501 ''' 502 Return json structure (timetuple filter). 503 504 *Parameters* 505 506 - **index** : integer, defaut 0 - timetuple format to apply : 507 - 0 : year 508 - 1 : month 509 - 2 : day 510 - 3 : hour 511 - 4 : minute 512 - 5 : seconds 513 - 6 : weekday 514 - 7 : yearday 515 - 8 : isdst (1 when daylight savings time is in effect, 0 when is not) 516 - **encoded** : defaut False - if True return string, else return dict 517 518 *Returns* : string or dict''' 519 if index not in [0,1,2,3,4,5,6,7,8] : return None 520 if self.stype == 'instant' : js = self.start.timetuple()[index] 521 elif self.stype == 'interval' : js = [self.start.timetuple()[index], self.end.timetuple()[index]] 522 if encoded : return json.dumps(js, cls=TimeSlotEncoder) 523 else : return js 524 525 def union(self, other): 526 ''' Add other's values to self's values in a new TimeInterval 527 if self and other are not disjoint''' 528 if self.link(other) != 'disjoint' : return TimeInterval([min(self.start, other.start), max(self.end, other.end)]) 529 else : return None 530 531 def _initInterval(self, val): 532 '''initialization of start and end dates from a list''' 533 self.start = self.end = self._initDat(val[0]) 534 if len(val) > 1 : self.end = self._initDat(val[1]) 535 else : self.start = self.end = self._initDat(val) 536 if self.end < self.start : self.start, self.end = self.end, self.start 537 538 def _initDat(self, val): 539 '''initialization of start and end dates from a unique value 540 (datetime, string, numpy.datetime64, pandas Timestamp)''' 541 if isinstance(val, datetime.datetime): 542 res = val 543 '''if val.tzinfo is None or val.tzinfo.utcoffset(val) is None: 544 res = val.astimezone(datetime.timezone.utc) 545 else: res = val''' 546 elif isinstance(val, str): 547 try : res = datetime.datetime.fromisoformat(val) 548 except: res = ES.nullDate 549 elif isinstance(val, numpy.datetime64): 550 res = pandas.Timestamp(val).to_pydatetime() 551 elif isinstance(val, pandas._libs.tslibs.timestamps.Timestamp): 552 res = val.to_pydatetime() 553 else : raise TimeSlotError("impossible to convert in a date") 554 return TimeInterval._dattz(res) 555 556 @staticmethod 557 def _dattz(val): 558 if val.tzinfo is None or val.tzinfo.utcoffset(val) is None: 559 return val.replace(tzinfo=datetime.timezone.utc) 560 return val 561 562class TimeSlotError(Exception): 563 pass 564
53class TimeSlotEncoder(json.JSONEncoder): 54 """add a new json encoder for TimeSlot""" 55 def default(self, o) : 56 if isinstance(o, datetime.datetime) : return o.isoformat() 57 return json.JSONEncoder.default(self, o)
add a new json encoder for TimeSlot
55 def default(self, o) : 56 if isinstance(o, datetime.datetime) : return o.isoformat() 57 return json.JSONEncoder.default(self, o)
Implement this method in a subclass such that it returns
a serializable object for o
, or calls the base implementation
(to raise a TypeError
).
For example, to support arbitrary iterators, you could implement default like this::
def default(self, o):
try:
iterable = iter(o)
except TypeError:
pass
else:
return list(iterable)
# Let the base class default method raise the TypeError
return JSONEncoder.default(self, o)
Inherited Members
- json.encoder.JSONEncoder
- JSONEncoder
- encode
- iterencode
59class TimeSlot: 60 ''' 61 *Attributes (for @property see methods)* : 62 63 - **slot** : list of `TimeInterval` 64 65 The methods defined in this class are : 66 67 *dynamic value property (getters)* 68 69 - `TimeSlot.Bounds` 70 - `TimeSlot.bounds` 71 - `TimeSlot.Centroid` 72 - `TimeSlot.duration` 73 - `TimeSlot.instant` 74 - `TimeSlot.middle` 75 - `TimeSlot.interval` 76 - `TimeSlot.stype` 77 78 *instance methods* 79 80 - `TimeSlot.json` 81 - `TimeSlot.link` 82 - `TimeSlot.timetuple` 83 - `TimeSlot.union` 84 ''' 85 def __init__(self, val=None): 86 ''' 87 TimeSlot constructor. 88 89 *Parameters* 90 91 - **val** : date, interval, list of interval (default None) - with several formats 92 (tuple, list, string, datetime, TimeSlot, TimeInterval, numpy datetime64, pandas timestamp) 93 94 *Returns* : None''' 95 slot = [] 96 if isinstance(val, str): 97 try: val = json.loads(val) 98 except: 99 val = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 100 #try: val = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 101 #except: val = None 102 if val == None : 103 self.slot = slot 104 return 105 if isinstance(val, tuple): val = list(val) 106 if isinstance(val, list) and len(val) == 2 and not isinstance(val[0], TimeInterval): 107 try : slot.append(TimeInterval(val)) 108 except : 109 for interv in val : slot.append(TimeInterval(interv)) 110 elif isinstance(val, list): 111 try : 112 for interv in val : slot.append(TimeInterval(interv)) 113 except : slot.append(TimeInterval(val)) 114 elif isinstance(val, datetime.datetime): slot.append(TimeInterval(val)) 115 elif isinstance(val, TimeSlot): slot = val.slot 116 elif isinstance(val, TimeInterval): slot.append(val) 117 else : slot.append(TimeInterval(val)) 118 self.slot= TimeSlot._reduced(slot) 119 120 def __add__(self, other): 121 ''' Add other's values to self's values in a new TimeSlot''' 122 return TimeSlot(TimeSlot._reduced(self.slot + other.slot)) 123 124 def __iadd__(self, other): 125 ''' Add other's values to self's values''' 126 self.slot = self._reduced(self.slot + other.slot) 127 128 def __contains__(self, item): 129 ''' item of extval''' 130 return item in self.slot 131 132 def __getitem__(self, index): 133 ''' return interval item''' 134 return self.slot[index] 135 136 def __setitem__(self, index, interv): 137 ''' modify interval item''' 138 if index < 0 or index >= len(self) : raise TimeSlotError("out of bounds") 139 self.slot[index] = TimeInterval(interv) 140 self.slot= TimeSlot._reduced(self.slot) 141 142 def __len__(self): 143 '''return the number of intervals included''' 144 return len(self.slot) 145 146 #def __repr__(self): 147 def __str__(self): 148 ''' return the type of slot and the json representation''' 149 return self.stype + '\n' + self.json(encoded=True, encode_format='json') 150 151 def __repr__(self): 152 #return self.__class__.__name__ + f'({self.slot})' 153 return self.__class__.__name__ + '(' + self.json(encoded=True, encode_format='json') + ')' 154 155 def __eq__(self, other): 156 '''equal if the slots are equals''' 157 try: return self.slot == other.slot 158 except: return False 159 160 def __lt__(self, other): 161 '''compare the earliest dates''' 162 return self.slot[0] < other.slot[0] 163 164 def __hash__(self): 165 return sum(hash(interv) for interv in self.slot) 166 #return hash(self.json(True)) 167 168 @property 169 def Bounds(self): 170 '''return an interval TimeSlot with the bounds of the TimeSlot object''' 171 return TimeSlot(self.bounds) 172 173 @property 174 def bounds(self): 175 '''return a tuple with the start and end dates with isoformat string''' 176 return (TimeSlot.form(self.slot[0].start), TimeSlot.form(self.slot[len(self) - 1].end)) 177 178 @classmethod 179 def cast(cls, value): 180 ''' 181 tranform a value (unique or list) in a list of `TimeSlot` 182 183 *Parameters* 184 185 - **value** : value to transform 186 187 *Returns* 188 189 - **list** : list of `TimeSlot` 190 ''' 191 if isinstance(value, list): 192 try : 193 return [cls(val) for val in value] 194 except : 195 return [cls(value)] 196 else : return [cls(value)] 197 198 @property 199 def Centroid(self): 200 '''return a TimeSlot with the date corresponding to the middle of the duration''' 201 return TimeSlot(self.instant) 202 203 @property 204 def duration(self): 205 '''cumulative duration of each interval (timedelta format)''' 206 duration = datetime.timedelta() 207 for interv in self.slot : duration += interv.duration 208 return duration 209 210 @staticmethod 211 def form(dtime): 212 if dtime.timetuple()[3:6]==(0,0,0): return dtime.date().isoformat() 213 return dtime.isoformat() 214 215 @property 216 def instant(self): 217 '''return the date corresponding to the middle of the duration (datetime format)''' 218 duration = self.duration / 2 219 for interv in self.slot : 220 if duration > interv.duration : 221 duration -= interv.duration 222 else : 223 return interv.start + duration 224 225 @property 226 def middle(self): 227 '''return the date corresponding to the middle of the bounds (datetime format)''' 228 return self.bounds.instant 229 230 @property 231 def name(self): 232 ''' class name''' 233 return self.__class__.__name__ 234 235 @property 236 def interval(self): 237 '''return a list with the start and end dates (datetime format)''' 238 return [self.slot[0].start, self.slot[len(self) - 1].end] 239 240 @property 241 def stype(self): 242 '''return a string with the type of TimeSlot (instant, interval, slot)''' 243 if len(self.slot) == 1 : return self.slot[0].stype 244 else : return 'slot' 245 246 def json(self, **kwargs): 247 ''' 248 Return json/bson structure with the list of TimeInterval. 249 250 *Parameters* 251 252 - **encoded** : defaut False - if False return dict, else return json string/bson bytes 253 - **encode_format** : defaut 'json' - return json, bson or cbor format 254 255 *Returns* : string or dict''' 256 option = {'encoded' : False, 'encode_format' : 'json'} | kwargs 257 if len(self) == 1 : js = self.slot[0].json(encoded=False, encode_format=option['encode_format']) 258 else : js = [interv.json(encoded=False, encode_format=option['encode_format']) for interv in self.slot] 259 if option['encoded'] and option['encode_format'] == 'json': return json.dumps(js, cls=TimeSlotEncoder) 260 if option['encoded'] and option['encode_format'] == 'bson': return bson.encode(js) 261 return js 262 263 def link(self, other): 264 ''' 265 Return the status (string) of the link between two TimeSlot (self and other). 266 - equals : if self and other are the same 267 - disjoint : if self's intervals and other's intervals are all disjoint 268 - within : if all self's intervals are included in other's intervals 269 - contains : if all other's intervals are included in self's intervals 270 - intersects : in the others cases 271 272 *Parameters* 273 274 - **other** : TimeSlot to be compared 275 276 *Returns* 277 278 - **tuple** : (string(status), boolean(full or not))''' 279 if self.stype == 'instant' : point, oslot = self[0], other 280 elif other.stype == 'instant' : point, oslot = other[0], self 281 else : point = None 282 if point is not None : 283 contains = equals = False 284 for interv in oslot: 285 contains = contains or interv.link(point) == 'contains' 286 equals = equals or interv.link(point) == 'equals' 287 if equals and not contains : return ('equals', True) 288 if contains and point == other[0] : return ('contains', True) 289 if contains and point == self[0] : return ('within', True) 290 return ('disjoint', True) 291 else : 292 union = self + other 293 link = 'intersects' 294 full = True 295 if union.duration == self.duration == other.duration : 296 full = len(union) == len(self) == len(other) 297 link = 'equals' 298 elif union.duration == self.duration : 299 full = len(union) == len(self) 300 link = 'contains' 301 elif union.duration == other.duration : 302 full = len(union) == len(other) 303 link = 'within' 304 elif union.duration == self.duration + other.duration : 305 full = len(union) == len(self) + len(other) 306 link = 'disjoint' 307 return (link, full) 308 309 def timetuple(self, index=0, encoded=False): 310 ''' 311 Return json structure with the list of TimeInterval (timetuple filter). 312 313 *Parameters* 314 315 - **index** : integer, defaut 0 - timetuple format to apply : 316 - 0 : year 317 - 1 : month 318 - 2 : day 319 - 3 : hour 320 - 4 : minute 321 - 5 : seconds 322 - 6 : weekday 323 - 7 : yearday 324 - 8 : isdst (1 when daylight savings time is in effect, 0 when is not) 325 - **encoded** : defaut False - if True return string, else return dict 326 327 *Returns* : string or dict''' 328 if len(self) == 1 : js = self.slot[0].timetuple(index, False) 329 else : js = [interv.timetuple(index, False) for interv in self.slot] 330 if encoded : return json.dumps(js, cls=TimeSlotEncoder) 331 else : return js 332 333 def union(self, other): 334 ''' Add other's values to self's values in a new TimeSlot (same as __add__)''' 335 return self.__add__(other) 336 337 @staticmethod 338 def _reduced(listinterv): 339 ''' return an ordered and non-overlapping list of TimeInterval from any TimeInterval list''' 340 if not isinstance(listinterv, list) or len(listinterv) == 0 : return [] 341 union = [] 342 slot = sorted(listinterv) 343 interv = slot[0] 344 i = j = 0 345 while i < len(slot) : 346 for j in range(i + 1, len(slot)): 347 if interv.link(slot[j]) == 'within' : interv = slot[j] 348 elif interv.link(slot[j]) == 'intersects' : interv = interv.union(slot[j]) 349 elif interv.link(slot[j]) == 'disjoint' : 350 union.append(interv) 351 interv = slot[j] 352 i = j 353 break 354 if j >= len(slot) - 1 : 355 union.append(interv) 356 break 357 return union
Attributes (for @property see methods) :
- slot : list of
TimeInterval
The methods defined in this class are :
dynamic value property (getters)
TimeSlot.Bounds
TimeSlot.bounds
TimeSlot.Centroid
TimeSlot.duration
TimeSlot.instant
TimeSlot.middle
TimeSlot.interval
TimeSlot.stype
instance methods
85 def __init__(self, val=None): 86 ''' 87 TimeSlot constructor. 88 89 *Parameters* 90 91 - **val** : date, interval, list of interval (default None) - with several formats 92 (tuple, list, string, datetime, TimeSlot, TimeInterval, numpy datetime64, pandas timestamp) 93 94 *Returns* : None''' 95 slot = [] 96 if isinstance(val, str): 97 try: val = json.loads(val) 98 except: 99 val = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 100 #try: val = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 101 #except: val = None 102 if val == None : 103 self.slot = slot 104 return 105 if isinstance(val, tuple): val = list(val) 106 if isinstance(val, list) and len(val) == 2 and not isinstance(val[0], TimeInterval): 107 try : slot.append(TimeInterval(val)) 108 except : 109 for interv in val : slot.append(TimeInterval(interv)) 110 elif isinstance(val, list): 111 try : 112 for interv in val : slot.append(TimeInterval(interv)) 113 except : slot.append(TimeInterval(val)) 114 elif isinstance(val, datetime.datetime): slot.append(TimeInterval(val)) 115 elif isinstance(val, TimeSlot): slot = val.slot 116 elif isinstance(val, TimeInterval): slot.append(val) 117 else : slot.append(TimeInterval(val)) 118 self.slot= TimeSlot._reduced(slot)
TimeSlot constructor.
Parameters
- val : date, interval, list of interval (default None) - with several formats (tuple, list, string, datetime, TimeSlot, TimeInterval, numpy datetime64, pandas timestamp)
Returns : None
178 @classmethod 179 def cast(cls, value): 180 ''' 181 tranform a value (unique or list) in a list of `TimeSlot` 182 183 *Parameters* 184 185 - **value** : value to transform 186 187 *Returns* 188 189 - **list** : list of `TimeSlot` 190 ''' 191 if isinstance(value, list): 192 try : 193 return [cls(val) for val in value] 194 except : 195 return [cls(value)] 196 else : return [cls(value)]
246 def json(self, **kwargs): 247 ''' 248 Return json/bson structure with the list of TimeInterval. 249 250 *Parameters* 251 252 - **encoded** : defaut False - if False return dict, else return json string/bson bytes 253 - **encode_format** : defaut 'json' - return json, bson or cbor format 254 255 *Returns* : string or dict''' 256 option = {'encoded' : False, 'encode_format' : 'json'} | kwargs 257 if len(self) == 1 : js = self.slot[0].json(encoded=False, encode_format=option['encode_format']) 258 else : js = [interv.json(encoded=False, encode_format=option['encode_format']) for interv in self.slot] 259 if option['encoded'] and option['encode_format'] == 'json': return json.dumps(js, cls=TimeSlotEncoder) 260 if option['encoded'] and option['encode_format'] == 'bson': return bson.encode(js) 261 return js
Return json/bson structure with the list of TimeInterval.
Parameters
- encoded : defaut False - if False return dict, else return json string/bson bytes
- encode_format : defaut 'json' - return json, bson or cbor format
Returns : string or dict
263 def link(self, other): 264 ''' 265 Return the status (string) of the link between two TimeSlot (self and other). 266 - equals : if self and other are the same 267 - disjoint : if self's intervals and other's intervals are all disjoint 268 - within : if all self's intervals are included in other's intervals 269 - contains : if all other's intervals are included in self's intervals 270 - intersects : in the others cases 271 272 *Parameters* 273 274 - **other** : TimeSlot to be compared 275 276 *Returns* 277 278 - **tuple** : (string(status), boolean(full or not))''' 279 if self.stype == 'instant' : point, oslot = self[0], other 280 elif other.stype == 'instant' : point, oslot = other[0], self 281 else : point = None 282 if point is not None : 283 contains = equals = False 284 for interv in oslot: 285 contains = contains or interv.link(point) == 'contains' 286 equals = equals or interv.link(point) == 'equals' 287 if equals and not contains : return ('equals', True) 288 if contains and point == other[0] : return ('contains', True) 289 if contains and point == self[0] : return ('within', True) 290 return ('disjoint', True) 291 else : 292 union = self + other 293 link = 'intersects' 294 full = True 295 if union.duration == self.duration == other.duration : 296 full = len(union) == len(self) == len(other) 297 link = 'equals' 298 elif union.duration == self.duration : 299 full = len(union) == len(self) 300 link = 'contains' 301 elif union.duration == other.duration : 302 full = len(union) == len(other) 303 link = 'within' 304 elif union.duration == self.duration + other.duration : 305 full = len(union) == len(self) + len(other) 306 link = 'disjoint' 307 return (link, full)
Return the status (string) of the link between two TimeSlot (self and other).
- equals : if self and other are the same
- disjoint : if self's intervals and other's intervals are all disjoint
- within : if all self's intervals are included in other's intervals
- contains : if all other's intervals are included in self's intervals
- intersects : in the others cases
Parameters
- other : TimeSlot to be compared
Returns
- tuple : (string(status), boolean(full or not))
309 def timetuple(self, index=0, encoded=False): 310 ''' 311 Return json structure with the list of TimeInterval (timetuple filter). 312 313 *Parameters* 314 315 - **index** : integer, defaut 0 - timetuple format to apply : 316 - 0 : year 317 - 1 : month 318 - 2 : day 319 - 3 : hour 320 - 4 : minute 321 - 5 : seconds 322 - 6 : weekday 323 - 7 : yearday 324 - 8 : isdst (1 when daylight savings time is in effect, 0 when is not) 325 - **encoded** : defaut False - if True return string, else return dict 326 327 *Returns* : string or dict''' 328 if len(self) == 1 : js = self.slot[0].timetuple(index, False) 329 else : js = [interv.timetuple(index, False) for interv in self.slot] 330 if encoded : return json.dumps(js, cls=TimeSlotEncoder) 331 else : return js
Return json structure with the list of TimeInterval (timetuple filter).
Parameters
- index : integer, defaut 0 - timetuple format to apply :
- 0 : year
- 1 : month
- 2 : day
- 3 : hour
- 4 : minute
- 5 : seconds
- 6 : weekday
- 7 : yearday
- 8 : isdst (1 when daylight savings time is in effect, 0 when is not)
- encoded : defaut False - if True return string, else return dict
Returns : string or dict
359class TimeInterval: # !!! interval 360 ''' 361 *Attributes (for @property see methods)* : 362 363 - **start** : datetime Object - start of `TimeInterval` 364 - **end** : datetime Object - end of `TimeInterval` 365 366 The methods defined in this class are : 367 368 *dynamic value property (getters)* 369 370 - `TimeInterval.Bounds` 371 - `TimeInterval.bounds` 372 - `TimeInterval.Centroid` 373 - `TimeInterval.duration` 374 - `TimeInterval.instant` 375 - `TimeInterval.stype` 376 377 *instance methods* 378 379 - `TimeInterval.json` 380 - `TimeInterval.link` 381 - `TimeInterval.timetuple` 382 - `TimeInterval.union` 383 ''' 384 def __init__(self, val= ES.nullDate): 385 ''' 386 TimeInterval constructor. 387 388 *Parameters* 389 390 - **val** : date, interval (default ES.nullDate) - with several formats 391 (list, string, datetime, TimeInterval, numpy datetime64, pandas timestamp) 392 393 *Returns* : None''' 394 self.start = self.end = ES.nullDate 395 if isinstance(val, str): 396 try: 397 sl = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 398 if sl != None : self.start = self.end = sl 399 return 400 except: 401 try: val = json.loads(val) 402 except: val = ES.nullDate 403 if isinstance(val, list) : self._initInterval(val) 404 elif isinstance(val, TimeInterval) : self.start, self.end = val.start, val.end 405 else : 406 dat = self._initDat(val) 407 if dat != None : self.start = self.end = dat 408 409 #def __repr__(self): 410 def __str__(self): 411 ''' return the type of interval and the json representation''' 412 return self.stype + '\n' + self.json(encoded=True, encode_format='json') 413 414 def __repr__(self): 415 #if self.stype == 'instant' : return self.__class__.__name__ + f'("{self.start}")' 416 #return self.__class__.__name__ + f'(["{self.start}","{self.end}"])' 417 return self.__class__.__name__ + '(' + self.json(encoded=True, encode_format='json') + ')' 418 419 def __eq__(self, other): 420 '''equal if the 'start' and 'end' dates are equals''' 421 return self.start == other.start and self.end == other.end 422 423 def __lt__(self, other): 424 '''compare the earliest dates (start)''' 425 return self.start < other.start 426 427 def __hash__(self): 428 return hash(self.start) + hash(self.end) 429 #return hash(self.json(True)) 430 431 @property 432 def bounds(self): 433 '''return a tuple with the start and end dates with isoformat string''' 434 return (TimeSlot.form(self.start), TimeSlot.form(self.end)) 435 436 @property 437 def Centroid(self): 438 '''return a TimeInterval with the date corresponding to the middle of the interval''' 439 return TimeInterval(self.instant) 440 441 @property 442 def duration(self): 443 '''duration between 'end' and 'start' date (timedelta format)''' 444 return self.end - self.start 445 446 @property 447 def instant(self): 448 '''return the date corresponding to the middle of the duration (datetime format)''' 449 return self.start + (self.end - self.start) / 2 450 451 @property 452 def stype(self): 453 '''return a string with the type of TimeInterval (instant, interval)''' 454 if self.start == self.end : return 'instant' 455 return 'interval' 456 457 def json(self, encoded=False, encode_format='json'): 458 ''' 459 Return json/bson structure (date if 'instant' or [start, end] if 'interval') 460 with datetime or datetime.isoformat for dates. 461 462 *Parameters* 463 464 - **encoded** : defaut False - if True return dict, else return json string/bson bytes 465 - **encode_format** : defaut 'json' - return json, bson or cbor format 466 467 *Returns* : string or dict''' 468 if self.stype == 'instant': js = self.start 469 else: js = [self.start, self.end] 470 '''if self.stype == 'instant' : 471 if encode_format == 'bson': js = self.start 472 else: 473 js = TimeSlot.form(self.start) 474 elif self.stype == 'interval' : 475 if encode_format == 'bson': js = [self.start, self.end] 476 else: js = [TimeSlot.form(self.start), TimeSlot.form(self.end)]''' 477 if encoded and encode_format == 'json': return json.dumps(js, cls=TimeSlotEncoder) 478 if encoded and encode_format == 'bson': return bson.encode(js) 479 return js 480 481 def link(self, other): 482 ''' 483 Return the status (string) of the link between two TimeIntervals (self and other). 484 - equals : if self and other are the same 485 - disjoint : if self's interval and other's interval are disjoint 486 - within : if other's interval is included in self's interval 487 - contains : if self's interval is included in other's interval 488 - intersects : in the others cases 489 490 *Parameters* 491 492 - **other** : TimeInterval to be compared 493 494 *Returns* : string''' 495 if self.start == other.start and self.end == other.end : return 'equals' 496 if self.start <= other.start and self.end >= other.end : return 'contains' 497 if self.start >= other.start and self.end <= other.end : return 'within' 498 if self.start <= other.end and self.end >= other.start : return 'intersects' 499 return 'disjoint' 500 501 def timetuple(self, index=0, encoded=False): 502 ''' 503 Return json structure (timetuple filter). 504 505 *Parameters* 506 507 - **index** : integer, defaut 0 - timetuple format to apply : 508 - 0 : year 509 - 1 : month 510 - 2 : day 511 - 3 : hour 512 - 4 : minute 513 - 5 : seconds 514 - 6 : weekday 515 - 7 : yearday 516 - 8 : isdst (1 when daylight savings time is in effect, 0 when is not) 517 - **encoded** : defaut False - if True return string, else return dict 518 519 *Returns* : string or dict''' 520 if index not in [0,1,2,3,4,5,6,7,8] : return None 521 if self.stype == 'instant' : js = self.start.timetuple()[index] 522 elif self.stype == 'interval' : js = [self.start.timetuple()[index], self.end.timetuple()[index]] 523 if encoded : return json.dumps(js, cls=TimeSlotEncoder) 524 else : return js 525 526 def union(self, other): 527 ''' Add other's values to self's values in a new TimeInterval 528 if self and other are not disjoint''' 529 if self.link(other) != 'disjoint' : return TimeInterval([min(self.start, other.start), max(self.end, other.end)]) 530 else : return None 531 532 def _initInterval(self, val): 533 '''initialization of start and end dates from a list''' 534 self.start = self.end = self._initDat(val[0]) 535 if len(val) > 1 : self.end = self._initDat(val[1]) 536 else : self.start = self.end = self._initDat(val) 537 if self.end < self.start : self.start, self.end = self.end, self.start 538 539 def _initDat(self, val): 540 '''initialization of start and end dates from a unique value 541 (datetime, string, numpy.datetime64, pandas Timestamp)''' 542 if isinstance(val, datetime.datetime): 543 res = val 544 '''if val.tzinfo is None or val.tzinfo.utcoffset(val) is None: 545 res = val.astimezone(datetime.timezone.utc) 546 else: res = val''' 547 elif isinstance(val, str): 548 try : res = datetime.datetime.fromisoformat(val) 549 except: res = ES.nullDate 550 elif isinstance(val, numpy.datetime64): 551 res = pandas.Timestamp(val).to_pydatetime() 552 elif isinstance(val, pandas._libs.tslibs.timestamps.Timestamp): 553 res = val.to_pydatetime() 554 else : raise TimeSlotError("impossible to convert in a date") 555 return TimeInterval._dattz(res) 556 557 @staticmethod 558 def _dattz(val): 559 if val.tzinfo is None or val.tzinfo.utcoffset(val) is None: 560 return val.replace(tzinfo=datetime.timezone.utc) 561 return val
Attributes (for @property see methods) :
- start : datetime Object - start of
TimeInterval
- end : datetime Object - end of
TimeInterval
The methods defined in this class are :
dynamic value property (getters)
TimeInterval.Bounds
TimeInterval.bounds
TimeInterval.Centroid
TimeInterval.duration
TimeInterval.instant
TimeInterval.stype
instance methods
384 def __init__(self, val= ES.nullDate): 385 ''' 386 TimeInterval constructor. 387 388 *Parameters* 389 390 - **val** : date, interval (default ES.nullDate) - with several formats 391 (list, string, datetime, TimeInterval, numpy datetime64, pandas timestamp) 392 393 *Returns* : None''' 394 self.start = self.end = ES.nullDate 395 if isinstance(val, str): 396 try: 397 sl = TimeInterval._dattz(datetime.datetime.fromisoformat(val)) 398 if sl != None : self.start = self.end = sl 399 return 400 except: 401 try: val = json.loads(val) 402 except: val = ES.nullDate 403 if isinstance(val, list) : self._initInterval(val) 404 elif isinstance(val, TimeInterval) : self.start, self.end = val.start, val.end 405 else : 406 dat = self._initDat(val) 407 if dat != None : self.start = self.end = dat
TimeInterval constructor.
Parameters
- val : date, interval (default ES.nullDate) - with several formats (list, string, datetime, TimeInterval, numpy datetime64, pandas timestamp)
Returns : None
457 def json(self, encoded=False, encode_format='json'): 458 ''' 459 Return json/bson structure (date if 'instant' or [start, end] if 'interval') 460 with datetime or datetime.isoformat for dates. 461 462 *Parameters* 463 464 - **encoded** : defaut False - if True return dict, else return json string/bson bytes 465 - **encode_format** : defaut 'json' - return json, bson or cbor format 466 467 *Returns* : string or dict''' 468 if self.stype == 'instant': js = self.start 469 else: js = [self.start, self.end] 470 '''if self.stype == 'instant' : 471 if encode_format == 'bson': js = self.start 472 else: 473 js = TimeSlot.form(self.start) 474 elif self.stype == 'interval' : 475 if encode_format == 'bson': js = [self.start, self.end] 476 else: js = [TimeSlot.form(self.start), TimeSlot.form(self.end)]''' 477 if encoded and encode_format == 'json': return json.dumps(js, cls=TimeSlotEncoder) 478 if encoded and encode_format == 'bson': return bson.encode(js) 479 return js
Return json/bson structure (date if 'instant' or [start, end] if 'interval') with datetime or datetime.isoformat for dates.
Parameters
- encoded : defaut False - if True return dict, else return json string/bson bytes
- encode_format : defaut 'json' - return json, bson or cbor format
Returns : string or dict
481 def link(self, other): 482 ''' 483 Return the status (string) of the link between two TimeIntervals (self and other). 484 - equals : if self and other are the same 485 - disjoint : if self's interval and other's interval are disjoint 486 - within : if other's interval is included in self's interval 487 - contains : if self's interval is included in other's interval 488 - intersects : in the others cases 489 490 *Parameters* 491 492 - **other** : TimeInterval to be compared 493 494 *Returns* : string''' 495 if self.start == other.start and self.end == other.end : return 'equals' 496 if self.start <= other.start and self.end >= other.end : return 'contains' 497 if self.start >= other.start and self.end <= other.end : return 'within' 498 if self.start <= other.end and self.end >= other.start : return 'intersects' 499 return 'disjoint'
Return the status (string) of the link between two TimeIntervals (self and other).
- equals : if self and other are the same
- disjoint : if self's interval and other's interval are disjoint
- within : if other's interval is included in self's interval
- contains : if self's interval is included in other's interval
- intersects : in the others cases
Parameters
- other : TimeInterval to be compared
Returns : string
501 def timetuple(self, index=0, encoded=False): 502 ''' 503 Return json structure (timetuple filter). 504 505 *Parameters* 506 507 - **index** : integer, defaut 0 - timetuple format to apply : 508 - 0 : year 509 - 1 : month 510 - 2 : day 511 - 3 : hour 512 - 4 : minute 513 - 5 : seconds 514 - 6 : weekday 515 - 7 : yearday 516 - 8 : isdst (1 when daylight savings time is in effect, 0 when is not) 517 - **encoded** : defaut False - if True return string, else return dict 518 519 *Returns* : string or dict''' 520 if index not in [0,1,2,3,4,5,6,7,8] : return None 521 if self.stype == 'instant' : js = self.start.timetuple()[index] 522 elif self.stype == 'interval' : js = [self.start.timetuple()[index], self.end.timetuple()[index]] 523 if encoded : return json.dumps(js, cls=TimeSlotEncoder) 524 else : return js
Return json structure (timetuple filter).
Parameters
- index : integer, defaut 0 - timetuple format to apply :
- 0 : year
- 1 : month
- 2 : day
- 3 : hour
- 4 : minute
- 5 : seconds
- 6 : weekday
- 7 : yearday
- 8 : isdst (1 when daylight savings time is in effect, 0 when is not)
- encoded : defaut False - if True return string, else return dict
Returns : string or dict
526 def union(self, other): 527 ''' Add other's values to self's values in a new TimeInterval 528 if self and other are not disjoint''' 529 if self.link(other) != 'disjoint' : return TimeInterval([min(self.start, other.start), max(self.end, other.end)]) 530 else : return None
Add other's values to self's values in a new TimeInterval if self and other are not disjoint
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback