|
2 | 2 | from datetime import datetime, timedelta, timezone
|
3 | 3 | from enum import Enum
|
4 | 4 | from logging import getLogger
|
5 |
| -import re |
6 | 5 | import urllib.parse
|
7 | 6 | from typing import Dict, List
|
8 | 7 |
|
9 |
| -import dateparser |
10 |
| - |
11 | 8 | from .common import MaybeOrderedDict, RGDOWNTIME_SCHEMA_URL, RGSUMMARY_SCHEMA_URL, Filters,\
|
12 | 9 | is_null, expand_attr_list_single, expand_attr_list, ensure_list
|
13 | 10 | from .contacts_reader import ContactsData
|
@@ -289,8 +286,8 @@ class Downtime(object):
|
289 | 286 | def __init__(self, rg: ResourceGroup, yaml_data: Dict):
|
290 | 287 | self.rg = rg
|
291 | 288 | self.data = yaml_data
|
292 |
| - self.start_time = self._parsetime(yaml_data["StartTime"]) |
293 |
| - self.end_time = self._parsetime(yaml_data["EndTime"]) |
| 289 | + self.start_time = self.parsetime(yaml_data["StartTime"]) |
| 290 | + self.end_time = self.parsetime(yaml_data["EndTime"]) |
294 | 291 |
|
295 | 292 | @property
|
296 | 293 | def timeframe(self) -> Timeframe:
|
@@ -367,28 +364,39 @@ def _expand_downtime(self, service_filter=None) -> MaybeOrderedDict:
|
367 | 364 | new_downtime["CreatedTime"] = "Not Available"
|
368 | 365 | new_downtime["UpdateTime"] = "Not Available"
|
369 | 366 |
|
370 |
| - fmt = "%b %d, %Y %H:%M %p %Z" |
371 |
| - new_downtime["StartTime"] = self.start_time.strftime(fmt) |
372 |
| - new_downtime["EndTime"] = self.end_time.strftime(fmt) |
| 367 | + output_fmt = "%b %d, %Y %H:%M %p %Z" |
| 368 | + new_downtime["StartTime"] = self.start_time.strftime(output_fmt) |
| 369 | + new_downtime["EndTime"] = self.end_time.strftime(output_fmt) |
373 | 370 |
|
374 | 371 | for k in ["ID", "Class", "Severity", "Description"]:
|
375 | 372 | new_downtime[k] = self.data.get(k, None)
|
376 | 373 |
|
377 | 374 | return new_downtime
|
378 | 375 |
|
379 | 376 | @staticmethod
|
380 |
| - def _parsetime(time_str: str) -> datetime: |
381 |
| - # get rid of stupid times like "00:00 AM" or "17:00 PM" |
382 |
| - if re.search(r"\s+00:\d\d\s+AM", time_str): |
383 |
| - time_str = time_str.replace(" AM", "") |
384 |
| - elif re.search(r"\s+(1[3-9]|2[0-3]):\d\d\s+PM", time_str): |
385 |
| - time_str = time_str.replace(" PM", "") |
386 |
| - time = dateparser.parse(time_str) |
387 |
| - if not time: |
388 |
| - raise ValueError("Invalid time {0}".format(time_str)) |
389 |
| - if not time.tzinfo: |
390 |
| - time = time.replace(tzinfo=timezone.utc) |
391 |
| - return time |
| 377 | + def parsetime(time_str: str) -> datetime: |
| 378 | + """Parse the downtime found in the YAML file; tries multiple formats, |
| 379 | + returns the first one that matches. |
| 380 | +
|
| 381 | + Raises ValueError if time_str cannot be parsed with any of the formats. |
| 382 | + """ |
| 383 | + |
| 384 | + fmts = ["%b %d, %Y %H:%M %z", # preferred format, e.g. "Mar 7, 2017 03:00 -0500" |
| 385 | + "%b %d, %Y %H:%M UTC", # explicit UTC timezone |
| 386 | + "%b %d, %Y %H:%M", # without timezone (assumes UTC) |
| 387 | + "%b %d, %Y %H:%M %p UTC"] # format existing data is in, e.g. "Mar 7, 2017 03:00 AM UTC" |
| 388 | + |
| 389 | + time = None |
| 390 | + for fmt in fmts: |
| 391 | + try: |
| 392 | + time = datetime.strptime(time_str, fmt) |
| 393 | + except ValueError: |
| 394 | + pass |
| 395 | + if time: |
| 396 | + if not time.tzinfo: |
| 397 | + time = time.replace(tzinfo=timezone.utc) |
| 398 | + return time |
| 399 | + raise ValueError("Cannot parse time {}".format(time_str)) |
392 | 400 |
|
393 | 401 |
|
394 | 402 | class Topology(object):
|
|
0 commit comments