Skip to content
This repository was archived by the owner on Aug 8, 2024. It is now read-only.

Commit f542b1b

Browse files
author
Rory McCann
committed
When parsing datetimes, parse out the timezone, and returns this
see #9
1 parent 338f5f4 commit f542b1b

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

apache_log_parser/__init__.py

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import re
2-
from datetime import datetime
2+
from datetime import datetime, tzinfo, timedelta
33

44
import user_agents
55

@@ -58,23 +58,81 @@ def parse_user_agent(matched_strings):
5858

5959
return matched_strings
6060

61+
class FixedOffset(tzinfo):
62+
"""Fixed offset in minutes east from UTC."""
63+
64+
def __init__(self, string):
65+
#import pudb ; pudb.set_trace()
66+
if string[0] == '-':
67+
direction = -1
68+
string = string[1:]
69+
elif string[0] == '+':
70+
direction = +1
71+
string = string[1:]
72+
else:
73+
direction = +1
74+
string = string
75+
76+
hr_offset = int(string[0:2], 10)
77+
min_offset = int(string[2:3], 10)
78+
min_offset = hr_offset * 60 + min_offset
79+
min_offset = direction * min_offset
80+
81+
self.__offset = timedelta(minutes = min_offset)
82+
83+
self.__name = string
84+
85+
def utcoffset(self, dt):
86+
return self.__offset
87+
88+
def tzname(self, dt):
89+
return self.__name
90+
91+
def dst(self, dt):
92+
return timedelta(0)
93+
94+
def __repr__(self):
95+
return repr(self.__name)
6196

6297

6398
def apachetime(s):
6499
"""
65100
Given a string representation of a datetime in apache format (e.g.
66-
"01/Sep/2012:06:05:11 +0000"), return the python datetime for that string
101+
"01/Sep/2012:06:05:11 +0000"), return the python datetime for that string, with timezone
67102
"""
68103
month_map = {'Jan': 1, 'Feb': 2, 'Mar':3, 'Apr':4, 'May':5, 'Jun':6, 'Jul':7,
69104
'Aug':8, 'Sep': 9, 'Oct':10, 'Nov': 11, 'Dec': 12}
70105
s = s[1:-1]
71-
return datetime(int(s[7:11]), month_map[s[3:6]], int(s[0:2]), \
72-
int(s[12:14]), int(s[15:17]), int(s[18:20]))
106+
107+
tz_string = s[21:26]
108+
tz = FixedOffset(tz_string)
109+
110+
obj = datetime(year=int(s[7:11]), month=month_map[s[3:6]], day=int(s[0:2]),
111+
hour=int(s[12:14]), minute=int(s[15:17]), second=int(s[18:20]),
112+
tzinfo=tz )
113+
114+
return obj
73115

74116
def format_time(matched_strings):
117+
75118
time_received = matched_strings['time_received']
119+
120+
# Parse it to a timezone string
76121
obj = apachetime(time_received)
77-
return {'time_received':time_received, 'time_received_datetimeobj': obj, 'time_received_isoformat': obj.isoformat()}
122+
123+
# For backwards compatibility, time_received_datetimeobj is a naive
124+
# datetime, so we have to create a timezone less version
125+
naive_obj = obj.replace(tzinfo=None)
126+
127+
utc = FixedOffset('0000')
128+
utc_obj = obj.astimezone(utc)
129+
130+
return {
131+
'time_received':time_received,
132+
'time_received_datetimeobj': naive_obj, 'time_received_isoformat': naive_obj.isoformat(),
133+
'time_received_tz_datetimeobj': obj, 'time_received_tz_isoformat': obj.isoformat(),
134+
'time_received_utc_datetimeobj': utc_obj, 'time_received_utc_isoformat': utc_obj.isoformat(),
135+
}
78136

79137

80138
FORMAT_STRINGS = [

apache_log_parser/tests.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ def test_pr8(self):
4242
'time_received_datetimeobj': datetime.datetime(2014, 11, 28, 10, 3, 40),
4343
'time_received_isoformat': '2014-11-28T10:03:40', 'remote_host': '127.0.0.1',
4444
'time_received': '[28/Nov/2014:10:03:40 +0000]',
45+
'time_received_tz_datetimeobj': datetime.datetime(2014, 11, 28, 10, 3, 40, tzinfo=apache_log_parser.FixedOffset("0000")),
46+
'time_received_tz_isoformat': '2014-11-28T10:03:40+00:00', 'remote_host': '127.0.0.1',
47+
'time_received_utc_datetimeobj': datetime.datetime(2014, 11, 28, 10, 3, 40, tzinfo=apache_log_parser.FixedOffset("0000")),
48+
'time_received_utc_isoformat': '2014-11-28T10:03:40+00:00', 'remote_host': '127.0.0.1',
4549
'extension_ssl_cipher': 'MY-CYPHER',
4650
})
4751

@@ -77,6 +81,10 @@ def test_issue9(self):
7781
'time_received': '[08/Mar/2015:18:06:58 -0400]',
7882
'time_received_datetimeobj': datetime.datetime(2015, 3, 8, 18, 6, 58),
7983
'time_received_isoformat': '2015-03-08T18:06:58',
84+
'time_received_tz_datetimeobj': datetime.datetime(2015, 3, 8, 18, 6, 58, tzinfo=apache_log_parser.FixedOffset('-0400')),
85+
'time_received_tz_isoformat': '2015-03-08T18:06:58-04:00',
86+
'time_received_utc_datetimeobj': datetime.datetime(2015, 3, 8, 22, 6, 58, tzinfo=apache_log_parser.FixedOffset('0000')),
87+
'time_received_utc_isoformat': '2015-03-08T22:06:58+00:00',
8088
})
8189

8290
if __name__ == '__main__':

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy