I've stepped through this and checked every value with pdb trace but can't figure out why I'm getting a KeyError, everything has its expected value. This is the function:
def get_formatted_timestamp(date_field, time_field):
# expects date_field = yyyy-M-d
# expects time_field = H:m:s
# outputs yyyy-MM-ddTHH:mm:ss:SSSZ ('T' and 'Z' are literals)
dt = date_field.strip().split('/')
tm = time_field.strip().split(':')
if len(dt) != 3 or len(tm) != 3 or len(dt[0]) != 4:
print 'invalid date or time: {} {}'.format(date_field, time_field)
return '1900-01-01T00:00:00.000Z' # error date value
y = dt[0]
M = dt[1] if len(dt[1]) == 2 else '0'+dt[1]
d = dt[2] if len(dt[2]) == 2 else '0'+dt[2]
H = tm[0] if len(tm[0]) == 2 else '0'+tm[0]
m = tm[1] if len(tm[1]) == 2 else '0'+tm[1]
s = tm[2] if len(tm[2]) == 2 else '0'+tm[2]
return '{y}-{M}-{d}T{H}:{m}:{s}.000Z'.format(y, M, d, H, m, s) # KeyError
The error is:
KeyError: 'y'
However, y
has a proper year string value (I checked repr(y)
; it is a string as expected). I also checked that dt[0]
was valid, and it is showing a proper year value.
Why is it throwing a KeyError when everything has an expected value? I'm stumped.
Here is the pdb output where I checked every value manually:
(Pdb) print repr(dt[0])
'2014'
(Pdb) print repr(y)
'2014'
(Pdb) print repr(M)
'02'
(Pdb) print repr(d)
'10'
(Pdb) print repr(H)
'15'
(Pdb) print repr(m)
'35'
(Pdb) print repr(s)
'19'
You don't have a key y
, because you don't have any keyword arguments. You only have positional arguments. That's not the same thing; even if you used a variable with that name doesn't mean that it is also a keyword argument.
Either use digits to pull out positional arguments, or use actual keyword arguments. If all your local variables match the slot names, you can use locals()
to provide those keyword arguments:
return '{y}-{M}-{d}T{H}:{m}:{s}.000Z'.format(**locals())
but otherwise you'd have to give each name used in the format an actual keyword:
return '{y}-{M}-{d}T{H}:{m}:{s}.000Z'.format(y=y, M=M, d=d, H=H, m=m, s=s)
Note that your code appears to reinvent the date-parsing and date-formatting wheels. The following would do the same thing but also validate that you have a valid date (e.g. no February 29th outside of a leap year, etc.):
from datetime import datetime
def get_formatted_timestamp(date_field, time_field):
# expects date_field = yyyy-M-d
# expects time_field = H:m:s
# outputs yyyy-MM-ddTHH:mm:ss.000Z ('T' and 'Z' are literals)
try:
dt = datetime.strptime('{} {}'.format(date_field, time_field), '%Y-%m-%d %H:%M:%S')
except ValueError:
return '1900-01-01T00:00:00.000Z' # error date value
return dt.strftime('%Y-%m-%dT%H:%M:%S.000Z')