patternpythonMinor
Effective way to handle multiple time string to timestamp
Viewed 0 times
handlewaytimemultipletimestampeffectivestring
Problem
I have 4 cases of time string as follow:
I want to convert string to timestamps. Based on this question, I need to declare 4 cases of pattern. I am looking forward to improve my solution.
The following code is my solution:
- s = "July 5, 2016, 12:04 a.m."
- s = "July 5, 2016, 7 a.m."
- s = "July 5, 2016, midnight."
- s = "July 5, 2016, noon."
I want to convert string to timestamps. Based on this question, I need to declare 4 cases of pattern. I am looking forward to improve my solution.
The following code is my solution:
import time
import datetime
s1 = "July 5, 2016, 12:04 a.m."
s2 = "July 5, 2016, 7 a.m."
s3 = "July 5, 2016, midnight."
s4 = "July 5, 2016, noon."
def convert(timestring):
# clear dot
timestring = timestring.replace(".","")
# convert s3 and s4 to s1 and s2
timestring = timestring.replace("midnight", "12:00 am") if "midnight" in timestring else timestring
timestring = timestring.replace("noon", "12:00 pm") if "noon" in timestring else timestring
result = None
try:
# try to match s2
print(timestring)
result = time.mktime(datetime.datetime.strptime(timestring, "%B %d, %Y, %I %p").timetuple())
except ValueError as e:
try:
result = time.mktime(datetime.datetime.strptime(timestring, "%B %d, %Y, %I:%M %p").timetuple())
except ValueError as e:
print(e)
print(result)
def main():
convert(s1)
convert(s2)
convert(s3)
convert(s4)
if __name__ == '__main__':
main()Solution
It's not really appropriate to print the result or the exception message instead of returning the result or throwing the exception.
It's not right to eliminate all dots from the input before proceeding.
I think that a good strategy would be to transform the input into a canonical representation. You've started along that path by replacing
A doctest seems very appropriate here, both for documentation and as a unit test.
It's not right to eliminate all dots from the input before proceeding.
I think that a good strategy would be to transform the input into a canonical representation. You've started along that path by replacing
"midnight" and "noon" with "12:00 am" and "12:00 pm", respectively. You could go further and set the minutes to ":00" if necessary. To accomplish that, I would use regular expression matching.A doctest seems very appropriate here, both for documentation and as a unit test.
from datetime import datetime
import re
from time import mktime
def convert(timestring):
"""
Convert a time string, in one of four accepted formats, in the
local time zone, into the number of seconds since the Epoch.
>>> import os, time
>>> os.environ['TZ'] = 'US/Pacific'
>>> time.tzset()
>>> convert("July 5, 2016, 12:04 a.m.")
1467702240.0
>>> convert("July 5, 2016, 7 a.m.")
1467727200.0
>>> convert("July 5, 2016, midnight.")
1467702000.0
>>> convert("July 5, 2016, noon.")
1467745200.0
>>> convert("2016-07-05 12:34:56")
Traceback (most recent call last):
...
ValueError: time data '2016-07-05 12:34:56' does not match format '%B %d, %Y, %I:%M %p'
"""
match = re.match(
'(?P.*)\s+'
'(?:(?Pnoon)|midnight|'
'(?P1?[0-9])(?::(?P[0-5]?[0-9]))?'
'\s+(?:(?Pp)|a)\.?m)\.,
timestring
)
if match:
# Canonicalize the time of day as "HH:MM am/pm"
timestring = '{date} {hh}:{mm} {ampm}'.format(
date=match.group('date'),
hh=match.group('hour') or '12',
mm=match.group('minute') or '00',
ampm=['am', 'pm'][bool(match.group('pm') or match.group('noon'))]
)
return mktime(
datetime.strptime(timestring, '%B %d, %Y, %I:%M %p').timetuple()
)Code Snippets
from datetime import datetime
import re
from time import mktime
def convert(timestring):
"""
Convert a time string, in one of four accepted formats, in the
local time zone, into the number of seconds since the Epoch.
>>> import os, time
>>> os.environ['TZ'] = 'US/Pacific'
>>> time.tzset()
>>> convert("July 5, 2016, 12:04 a.m.")
1467702240.0
>>> convert("July 5, 2016, 7 a.m.")
1467727200.0
>>> convert("July 5, 2016, midnight.")
1467702000.0
>>> convert("July 5, 2016, noon.")
1467745200.0
>>> convert("2016-07-05 12:34:56")
Traceback (most recent call last):
...
ValueError: time data '2016-07-05 12:34:56' does not match format '%B %d, %Y, %I:%M %p'
"""
match = re.match(
'(?P<date>.*)\s+'
'(?:(?P<noon>noon)|midnight|'
'(?P<hour>1?[0-9])(?::(?P<minute>[0-5]?[0-9]))?'
'\s+(?:(?P<pm>p)|a)\.?m)\.$',
timestring
)
if match:
# Canonicalize the time of day as "HH:MM am/pm"
timestring = '{date} {hh}:{mm} {ampm}'.format(
date=match.group('date'),
hh=match.group('hour') or '12',
mm=match.group('minute') or '00',
ampm=['am', 'pm'][bool(match.group('pm') or match.group('noon'))]
)
return mktime(
datetime.strptime(timestring, '%B %d, %Y, %I:%M %p').timetuple()
)Context
StackExchange Code Review Q#134006, answer score: 2
Revisions (0)
No revisions yet.