def decode_datetime(encoded_datetime):
  # Check if the string includes a time zone offset.  Break out the
  # part that doesn't include time zone info.  Convert to uppercase
  # because all our comparisons should be case-insensitive.
  time_zone_match = _TIME_ZONE_RE.search(encoded_datetime)
  if time_zone_match:
    time_string = encoded_datetime[:time_zone_match.start(1)].upper()
  else:
    time_string = encoded_datetime.upper()

  if '.' in time_string:
    format_string = '%Y-%m-%dT%H:%M:%S.%f'
  else:
    format_string = '%Y-%m-%dT%H:%M:%S'

  decoded_datetime = datetime.datetime.strptime(time_string, format_string)

  if not time_zone_match:
    return decoded_datetime

  # Time zone info was included in the parameter.  Add a tzinfo
  # object to the datetime.  Datetimes can't be changed after they're
  # created, so we'll need to create a new one.
  if time_zone_match.group('z'):
    offset_minutes = 0
  else:
    sign = time_zone_match.group('sign')
    hours, minutes = [int(value) for value in
                      time_zone_match.group('hours', 'minutes')]
    offset_minutes = hours * 60 + minutes
    if sign == '-':
      offset_minutes *= -1

  return datetime.datetime(decoded_datetime.year,
                           decoded_datetime.month,
                           decoded_datetime.day,
                           decoded_datetime.hour,
                           decoded_datetime.minute,
                           decoded_datetime.second,
                           decoded_datetime.microsecond,
                           TimeZoneOffset(offset_minutes))
Decode a DateTimeField parameter from a string to a python datetime.
dataset/ETHPy150Open AppScale/appscale/AppServer/lib/protorpc/protorpc/util.py/decode_datetime