-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtiming.py
133 lines (107 loc) · 3.96 KB
/
timing.py
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
import datetime
import pytz
import re
def hour_to_24(hour, meridian):
"""
Converts a 12-hour representation to a 24-hour representation.
e.g.
12, "AM" => 0
6, "AM" => 6
12, "PM" => 12
3, "PM" => 15
11, "PM" => 23
"""
# first, if it's 12 whatever, subtract the 12 because it's actually 0
if hour == 12:
hour -= 12
# if it's PM, add 12
if meridian == "PM":
hour += 12
return hour
def parse_datetime_tuple(dt_tuple):
"""
Converts a tuple like ('11', '27', '17', '5', '45', 'PM')
into a proper Python datetime object.
It MUST be 6 elements long and have exactly the right
order of elements.
"""
if len(dt_tuple) != 6:
raise ValueError
# abbreviate for simplicity
R = dt_tuple
# convert this to a datetime
# year is encoded as 2-digit
year = 2000 + int(R[2])
month = int(R[0])
day = int(R[1])
# need to convert this 12-hour representation to 24-hours
hour = hour_to_24(int(R[3]), R[5])
minute = int(R[4])
# no seconds
# TODO: set timezone as EST; see
# https://docs.python.org/2/library/datetime.html#datetime-objects
# it's something like
# timezone = pytz.timezone("America/New_York")
dt = datetime.datetime(year, month, day, hour, minute)
return dt
def parse_raw_occurrence_data(occurrence_array):
"""
Parses a list of 2 elements that represents
when an incident occurred. The following formats
are all supported:
["11/28/17","4:20 PM"],
["11/21/17","2:00 PM - 6:00 PM"],
["11/27/17 - 5:45 PM","11/28/17 - 9:00 AM"]
Transforms this into a timestamp of when it started and ended;
returns a tuple of Python datetime objects (start, end).
If you want to convert a time range, use both elements of the outputted
tuple. If you want to convert a singular time, this function works too,
but only use one element of the outputted tuple.
"""
# concatenate and trim whitespace
occurrence = (occurrence_array[0] + " | " + occurrence_array[1]).strip()
start = None
end = None
# CASE I: simplest, occurred at a constant time and not a range
simple_matcher = re.compile(
"^(\d{1,2})\/(\d{1,2})\/(\d{2}) \| (\d{1,2}):(\d{2}) ([A|P]M)$")
simple_result = simple_matcher.findall(occurrence)
if len(simple_result) > 0:
# this matches Case I
# return group length = 6
# abbreviate this for simplicity
R = simple_result[0]
start = parse_datetime_tuple(R)
# end time is same as start time
end = start
# CASE II: range of times on the SAME day
range_matcher = re.compile(
"^(\d{1,2})\/(\d{1,2})\/(\d{2}) \| (\d{1,2}):(\d{2}) ([A|P]M) - (\d{1,2}):(\d{2}) ([A|P]M)$")
range_result = range_matcher.findall(occurrence)
if len(range_result) > 0:
# this matches Case II
# return group length = 9
# abbreviate this for simplicity
R = range_result[0]
# convert to datetime
# start has R[0, 1, 2, 3, 4, 5]
# end has R[0, 1, 2, 6, 7, 8]
start_tuple = R[0:6]
start = parse_datetime_tuple(start_tuple)
end_tuple = (R[0], R[1], R[2], R[6], R[7], R[8])
end = parse_datetime_tuple(end_tuple)
# CASE III: range of times ACROSS days
# TODO: break this down across lines
across_day_matcher = re.compile(
"^(\d{1,2})\/(\d{1,2})\/(\d{2}) - (\d{1,2}):(\d{2}) ([A|P]M) \| (\d{1,2})\/(\d{1,2})\/(\d{2}) - (\d{1,2}):(\d{2}) ([A|P]M)$")
across_day_result = across_day_matcher.findall(occurrence)
if len(across_day_result) > 0:
# this matches Case III
# return group length = 12
# abbreviate this for simplicity
R = across_day_result[0]
# convert start and end for datetime
# start is encoded as elements [0,6); end is [6, 12)
start = parse_datetime_tuple(R[0:6])
end = parse_datetime_tuple(R[6:12])
return (start, end)