Skip to content

Instantly share code, notes, and snippets.

@pglezen
Created October 22, 2017 20:08
Show Gist options
  • Save pglezen/233c2228e65655938e53c0037c4de029 to your computer and use it in GitHub Desktop.
Save pglezen/233c2228e65655938e53c0037c4de029 to your computer and use it in GitHub Desktop.
Parsing timestamps with Z in Python
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Parsing Date/Time Strings with Z\n",
"\n",
"The `datetime.strptime()` function does not handle a standard\n",
"timezone indicator specified as a `Z` on the end, which stands\n",
"for universal time. The string `2017-10-23T22:15:00Z` is the\n",
"kind of timestamp I might receive from the GitHub API for a\n",
"commit time."
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2017-10-23 22:15:00\n"
]
}
],
"source": [
"from datetime import datetime\n",
"from datetime import timezone\n",
"\n",
"xml_str_wz = '2017-10-23T22:15:00Z'\n",
"xml_datetime_fmt = '%Y-%m-%dT%H:%M:%SZ'\n",
"\n",
"dt1 = datetime.strptime(xml_str_wz, xml_datetime_fmt)\n",
"print(dt1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One thing that is suspicious about this commit timestamp\n",
"for me is that I don't often commit changes past 10 pm;\n",
"I'm more of an early person. But the `Z` on the end is\n",
"timezone information which I ignored during the parse.\n",
"In particular, `Z` means UTC time. I can impose this\n",
"manually."
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2017-10-23 22:15:00+00:00\n"
]
}
],
"source": [
"dt1 = dt1.replace(tzinfo=timezone.utc)\n",
"print(dt1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now that this object contains timezone information,\n",
"I can render it in my local time zone."
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2017-10-23 15:15:00-07:00\n"
]
}
],
"source": [
"print(dt1.astimezone())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"3:15 pm is much more like it.\n",
"\n",
"The `Z` is part of the ISO specification; but for some reason\n",
"there is no\n",
"[Python parse character](https://docs.python.org/3.5/library/datetime.html#strftime-and-strptime-behavior)\n",
"to handle it. The `%z` comes closest, but it demands explicit offsets."
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"time data '2017-10-23T22:15:00Z' does not match format '%Y-%m-%dT%H:%M:%S%z'\n"
]
}
],
"source": [
"try:\n",
" dt2 = datetime.strptime(xml_str_wz, '%Y-%m-%dT%H:%M:%S%z')\n",
" print(dt2.astimezone())\n",
"except ValueError as valueErr:\n",
" print(valueErr)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"But it works if the explicit offset is provided."
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2017-10-23 15:15:00-07:00\n"
]
}
],
"source": [
"dt2 = datetime.strptime('2017-10-23T22:15:00+0000', '%Y-%m-%dT%H:%M:%S%z')\n",
"print(dt2.astimezone())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"When I expect a datetime with a `Z` on the end, I provide a\n",
"function to parse it like this."
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"('NULL',\n",
" 'NULL',\n",
" 'NULL',\n",
" datetime.datetime(2017, 10, 23, 22, 15, tzinfo=datetime.timezone.utc))"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def parseTimeZ(timeStrZ):\n",
" xml_fmt = '%Y-%m-%dT%H:%M:%SZ'\n",
" null_response = 'NULL'\n",
" if timeStrZ == None:\n",
" timeStrZ = ''\n",
" try:\n",
" result = datetime.strptime(timeStrZ, xml_fmt).replace(tzinfo=timezone.utc)\n",
" except ValueError:\n",
" result = null_response\n",
" return result\n",
"\n",
"(parseTimeZ(None), \n",
" parseTimeZ(''), \n",
" parseTimeZ('2017-10-23T22:15:00'), \n",
" parseTimeZ('2017-10-23T22:15:00Z'))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python (p3)",
"language": "python",
"name": "p3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.3"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment