{"id":20563,"date":"2018-05-10T10:40:35","date_gmt":"2018-05-10T14:40:35","guid":{"rendered":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/"},"modified":"2022-11-14T15:42:29","modified_gmt":"2022-11-14T20:42:29","slug":"work-dates-time-python","status":"publish","type":"post","link":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/","title":{"rendered":"How to work with dates and time with Python"},"content":{"rendered":"<div class='bbg-row bbg-bg--white  bbg-row--margin-top-none bbg-row--margin-bottom-none' data-anchor='row-6a0bca54dfdf0'>\n  \n\t\n\t\n\t<div class=\"bbg-row--content\">\n\t\t\n\t\t\t<div class='bbg-column bbg-column--width-8 bbg-column--offset-2'>\n\t<div class='bb-wysiwyg'>\n    \n    <p><em>Get a better understanding of datetime in Python with this primer by Senior Software Developer Mario Corchero.<\/em><\/p>\n<p><em>This article was originally\u00a0<a class=\"\" href=\"https:\/\/opensource.com\/article\/17\/5\/understanding-datetime-python-primer\">published on Opensource.com<\/a><span class=\"Apple-converted-space\">\u00a0<\/span>under the<span class=\"Apple-converted-space\">\u00a0<\/span><a class=\"rte-from-internet\" href=\"https:\/\/creativecommons.org\/licenses\/by-sa\/4.0\/\">CC BY-SA 4.0<\/a><span class=\"Apple-converted-space\">\u00a0<\/span>license. It has been updated by the author in preparation for the forthcoming release of Python 3.7.<\/em><\/p>\n\n<\/div>\n<div class=\"bb-separator\" data-color=\"\">\n\t<hr class=\"bb-separator__rule\">\n<\/div>\n<div class='bb-wysiwyg'>\n    \n    <p><img loading=\"lazy\" decoding=\"async\" class=\"image-full-size aligncenter\" title=\"How to work with dates and time with Python\" src=\"https:\/\/opensource.com\/sites\/default\/files\/styles\/image-full-size\/public\/lead-images\/clocks_time.png?itok=_ID09GDk\" alt=\"How to work with dates and time with Python\" width=\"610\" height=\"343\" \/><\/p>\n<h6 style=\"text-align: center;\">Image by: <a title=\"User:Ianezz\" href=\"https:\/\/commons.wikimedia.org\/wiki\/User:Ianezz\">Matteo Ianeselli<\/a>. Modified by Opensource.com. <a href=\"https:\/\/creativecommons.org\/licenses\/by\/3.0\/\" rel=\"nofollow\">CC-BY-3.0<\/a>.<\/h6>\n\n<\/div>\n<div class='bb-wysiwyg'>\n    \n    <p>When trying to make things work with the datetime module, most Python users have faced a point when we resort to guess-and-check until the errors go away. datetime is one of those APIs that seems easy to use, but requires the developer to have a deep understanding of what a few things actually mean. Otherwise, given the complexity of date- and time-related issues, introducing unexpected bugs is easy.<\/p>\n<h2>Time standards<\/h2>\n<p>The first concept to grasp when working with time is a standard that defines how we can measure units of time. The same way we have standards to measure weight or length that define kilograms or meters, we need an accurate way to define what a &#8216;<em>second&#8217;<\/em> means. We can then use other time references\u2014such as days, weeks, or years\u2014using a calendar standard as multiples of the second (see <a href=\"https:\/\/en.wikipedia.org\/wiki\/Gregorian_calendar\">Gregorian Calendar<\/a> as an example).<\/p>\n<h3>UT1<\/h3>\n<p>One of the simplest ways to measure a second is as a fraction of the day, given that we can reliably guarantee the sun will rise and set every day (in most places). This gave birth to Universal Time (UT1), the successor of GMT (Greenwich Mean Time). Today, we use stars and quasars to measure how long it takes for the Earth to perform a full rotation around the sun. Even if this seems precise enough, it still has issues; due to the gravitational pull of the moon, tides, and earthquakes, the days change length all year long. Although this is not a problem for most applications, it becomes a non-trivial problem when we require really precise measurements. GPS triangulation is a good example of a time-sensitive process, in which being a second off results in a completely different location on the globe.<\/p>\n<h3>TAI<\/h3>\n<p>As a result, the International Atomic Time (<a href=\"https:\/\/en.wikipedia.org\/wiki\/International_Atomic_Time\">TAI<\/a>) was designed to be as precise as possible. Using <a href=\"https:\/\/en.wikipedia.org\/wiki\/Atomic_clock\" target=\"_blank\" rel=\"noopener noreferrer\">atomic clocks<\/a> in multiple laboratories across the earth, we get the most accurate and constant measure of the second, which allows us to compute time intervals with the highest accuracy. This precision is both a blessing and a curse as TAI is so exact that it deviates from UT1 (or what we call <i>civil time)<\/i>. This means that we will eventually have our clock noon deviate substantially from the solar noon.<\/p>\n<h3>UTC<\/h3>\n<p>That led to the development of Coordinated Universal Time (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Coordinated_Universal_Time\" target=\"_blank\" rel=\"noopener noreferrer\">UTC<\/a>), which brought together the best of the both units. UTC uses the measurement of a second as defined by TAI. This allows for accurate measurement of time while introducing leap seconds to ensure that the time does not deviate from UT1 by more than 0.9 seconds.<\/p>\n<h3>How all this plays together on your computer<\/h3>\n<p>With all this background, you should now be able to understand how the operating system is serving time at any given moment. While the computer doesn&#8217;t have an atomic clock inside but uses an internal clock synchronized with the rest of the world via Network Time Protocol (<a href=\"https:\/\/www.ntp.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">NTP<\/a>).<\/p>\n<p>In Unix-like systems, the most common way to measure time is by using <a href=\"https:\/\/en.wikipedia.org\/wiki\/Unix_time\" target=\"_blank\" rel=\"noopener noreferrer\">POSIX time<\/a>, which is defined as the number of seconds that have elapsed the Unix epoch (Thursday, January 1, 1970), without taking leap seconds into account. As POSIX time does not handle leap seconds (nor does Python), some companies have defined their own way of handling time by smearing the leap second across the time around it through their NTP servers (see <a href=\"https:\/\/developers.google.com\/time\/smear\" target=\"_blank\" rel=\"noopener noreferrer\">Google time<\/a> as an example).<\/p>\n<h2>Time zones<\/h2>\n<p class=\"rtecenter\"><img loading=\"lazy\" decoding=\"async\" class=\"media-image attr__typeof__foaf:Image img__fid__350656 img__view_mode__default attr__format__default attr__field_file_image_alt_text&#091;und&#093;&#091;0&#093;&#091;value&#093;__Time zones maps attr__field_file_image_title_text&#091;und&#093;&#091;0&#093;&#091;value&#093;__Time map attr__field_file_image_caption&#091;und&#093;&#091;0&#093;&#091;value&#093;__&amp;lt;p&amp;gt;Hellerick, based on earlier image by CIA with many modifications other contributors, TimeZonesBoy (Based File:CIA WorldFactBook Time Zones.svg).&amp;amp;nbsp; Public domain or &amp;lt;a data-cke-saved-href=&amp;quot;https:\/\/creativecommons.org\/licenses\/by-sa\/4.0&amp;quot; href=&amp;quot;https:\/\/creativecommons.org\/licenses\/by-sa\/4.0&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;CC BY-SA 4.0&amp;lt;\/a&amp;gt;, via href=&amp;quot;https:\/\/upload.wikimedia.org\/wikipedia\/commons\/e\/e8\/Standard_World_Time_Zones.png&amp;quot; target=&amp;quot;_blank&amp;quot;&amp;gt;Wikimedia Commons&amp;lt;\/a&amp;gt;.&amp;lt;\/p&amp;gt; attr__field_file_image_caption&#091;und&#093;&#091;0&#093;&#091;format&#093;__panopoly_wysiwyg_text attr__field_folder&#091;und&#093;__9402 aligncenter\" title=\"Time zones map\" src=\"https:\/\/opensource.com\/sites\/default\/files\/standard_world_time_zones_0.png\" alt=\"Time zones maps\" width=\"567\" height=\"301\" \/><\/p>\n<p>I&#8217;ve explained what UTC is and how it allows us to define dates and times, but countries like to have their wall time noon match with the solar time for noon, so the sun is at the top of the sky at 12 PM. That is why UTC defines offsets, so we can have 12 AM with an offset of +4 hours from UTC. This effectively means that the actual time without offset is 8 AM.<\/p>\n<p>Governments define the standard offset from UTC that a geographical position follows, effectively creating a time zone. The most common database for time zones is known as the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Tz_database\" target=\"_blank\" rel=\"noopener noreferrer\">Olson Database<\/a>. This can be retrieved in Python using <a href=\"https:\/\/dateutil.readthedocs.io\/en\/stable\/tz.html\" target=\"_blank\" rel=\"noopener noreferrer\"><b>dateutil.tz<\/b><\/a>:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">from<\/span> dateutil<span style=\"color: #808030;\">.<\/span>tz <span style=\"color: #800000; font-weight: bold;\">import<\/span> gettz\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> gettz<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Madrid\"<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>The result of <strong>gettz<\/strong> gives us an object that we can use to create time-zone-aware dates in Python:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">import<\/span> datetime <span style=\"color: #800000; font-weight: bold;\">as<\/span> dt\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>now<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>isoformat<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'2017-04-15T14:16:56.551778'<\/span>  <span style=\"color: #696969;\"># This is a naive datetime<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>now<span style=\"color: #808030;\">(<\/span>gettz<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Madrid\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>isoformat<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'2017-04-15T14:17:01.256587+02:00'<\/span>  <span style=\"color: #696969;\"># This is a tz aware datetime, always prefer these<\/span>\r\n<\/pre>\n<p>We can see how to get the current time via the <b><a href=\"https:\/\/docs.python.org\/3.6\/library\/datetime.html#datetime.datetime.now\" target=\"_blank\" rel=\"noopener noreferrer\">now<\/a><\/b> function of datetime. On the second call we pass a <b><a href=\"https:\/\/docs.python.org\/3.6\/library\/datetime.html#datetime.tzinfo\" target=\"_blank\" rel=\"noopener noreferrer\">tzinfo<\/a><\/b> object which sets the time zone and displays the offset in the <a href=\"https:\/\/en.wikipedia.org\/wiki\/ISO_8601\" target=\"_blank\" rel=\"noopener noreferrer\">ISO string representation<\/a> of that datetime.<\/p>\n<p>Should we want to use just plain UTC in Python 3, we don&#8217;t need any external libraries:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>now<span style=\"color: #808030;\">(<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>isoformat<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'2017-04-15T12:22:06.637355+00:00'<\/span>\r\n<\/pre>\n<h2>DST<\/h2>\n<p>Once we grasp all this knowledge, we might feel prepared to work with time zones, but we must be aware of one more thing that happens in some time zones: Daylight Saving Time (DST).<\/p>\n<p>The countries that follow DST will move their clocks one hour forward in spring, and one hour backward in autumn to return to the standard time of the time zone. This effectively implies that a single time zone can have multiple offsets, as we can see in the following example:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">7<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>astimezone<span style=\"color: #808030;\">(<\/span>gettz<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Madrid\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'2017-07-01T02:00:00+02:00'<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>astimezone<span style=\"color: #808030;\">(<\/span>gettz<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Madrid\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'2017-01-01T01:00:00+01:00'<\/span>\r\n<\/pre>\n<p>This gives us days that are made of 23 or 25 hours, resulting in really interesting time arithmetic. Depending on the time and the time zone, adding a day does not necessarily mean adding 24 hours:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> today <span style=\"color: #808030;\">=<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">10<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">29<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>gettz<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Madrid\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> tomorrow <span style=\"color: #808030;\">=<\/span> today <span style=\"color: #44aadd;\">+<\/span> dt<span style=\"color: #808030;\">.<\/span>timedelta<span style=\"color: #808030;\">(<\/span>days<span style=\"color: #808030;\">=<\/span><span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> tomorrow<span style=\"color: #808030;\">.<\/span>astimezone<span style=\"color: #808030;\">(<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span> <span style=\"color: #44aadd;\">-<\/span> today<span style=\"color: #808030;\">.<\/span>astimezone<span style=\"color: #808030;\">(<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>timedelta<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">3600<\/span><span style=\"color: #808030;\">)<\/span>  <span style=\"color: #696969;\"># We've added 25 hours<\/span>\r\n<\/pre>\n<p>When working with timestamps, the best strategy is to use non DST-aware time zones (ideally UTC+00:00).<\/p>\n<h2>Serializing your datetime objects<\/h2>\n<p>The day will come that you need to send your datetime objects in <a href=\"https:\/\/www.json.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">JSON<\/a> and you will get the following:<\/p>\n<pre class=\"python geshifilter-python\"><span class=\"sy0\">&gt;&gt;&gt;<\/span> now <span class=\"sy0\">=<\/span> dt.<span class=\"kw3\">datetime<\/span>.<span class=\"me1\">now<\/span><span class=\"br0\">(<\/span>dt.<span class=\"me1\">timezone<\/span>.<span class=\"me1\">utc<\/span><span class=\"br0\">)<\/span>\r\n<span class=\"sy0\">&gt;&gt;&gt;<\/span> json.<span class=\"me1\">dumps<\/span><span class=\"br0\">(<\/span>now<span class=\"br0\">)<\/span>\r\n<span class=\"kw2\">TypeError<\/span>: Object of <span class=\"kw2\">type<\/span> <span class=\"st0\">'datetime'<\/span> <span class=\"kw1\">is<\/span> <span class=\"kw1\">not<\/span> JSON serializable<\/pre>\n<p>There are three main ways to serialize datetime in JSON:<\/p>\n<h3>String<\/h3>\n<p>datetime has two main functions to convert to and from a string given a specific format: <a href=\"https:\/\/docs.python.org\/2\/library\/datetime.html#strftime-strptime-behavior\" target=\"_blank\" rel=\"noopener noreferrer\"><strong>strftime<\/strong> and <b>strptime<\/b><\/a>. The best way is to use the standard <a href=\"https:\/\/en.wikipedia.org\/wiki\/ISO_8601\" target=\"_blank\" rel=\"noopener noreferrer\">ISO_8601<\/a> for serializing time-related objects as string, which is done by calling <b>isoformat<\/b> on the datetime object:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> now <span style=\"color: #808030;\">=<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>now<span style=\"color: #808030;\">(<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> json<span style=\"color: #808030;\">.<\/span>dumps<span style=\"color: #808030;\">(<\/span>now<span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #074726;\">TypeError<\/span><span style=\"color: #808030;\">:<\/span> <span style=\"color: #400000;\">Object<\/span> of <span style=\"color: #400000;\">type<\/span> <span style=\"color: #0000e6;\">'datetime'<\/span> <span style=\"color: #800000; font-weight: bold;\">is<\/span> <span style=\"color: #800000; font-weight: bold;\">not<\/span> JSON serializable\r\n<\/pre>\n<p>To get a datetime object from a string that was formatted using <b>isoformat<\/b> with a UTC time zone, we can rely on <b>strptime<\/b>:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>strptime<span style=\"color: #808030;\">(<\/span>now_str<span style=\"color: #808030;\">,<\/span> <span style=\"color: #0000e6;\">\"%Y-%m-%dT%H:%M:%S.%f+00:00\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>replace<span style=\"color: #808030;\">(<\/span>tzinfo<span style=\"color: #808030;\">=<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">4<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">19<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">21<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">49<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">5<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">542320<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>datetime<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>In this example, we are hard-coding the offset to be UTC and then setting it once the datetime object has been created. A better way to fully parse the string including the offset is by using the external library <b>dateutil:<\/b><\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">from<\/span> dateutil<span style=\"color: #808030;\">.<\/span>parser <span style=\"color: #800000; font-weight: bold;\">import<\/span> parse\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> parse<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">'2017-04-19T21:49:05.542320+00:00'<\/span><span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">4<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">19<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">21<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">49<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">5<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">542320<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>tzutc<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> parse<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">'2017-04-19T21:49:05.542320+01:00'<\/span><span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">4<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">19<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">21<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">49<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">5<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">542320<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>tzoffset<span style=\"color: #808030;\">(<\/span><span style=\"color: #074726;\">None<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">3600<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>Note, once we serialize and de-serialize, we lose the time zone information and keep only the offset.<\/p>\n<p>In Python 3.7, a new function &#8216;fromisoformat&#8217; will been added to datetime that will allow developers to parse datetimes from strings produced out of &#8216;isoformat.&#8217;<\/p>\n<h3>Integer<\/h3>\n<p>We are able to store a datetime as an integer by using the number of seconds that passed since a specific epoch (reference date). As I mentioned earlier, the most-known epoch in computer systems is the Unix epoch, which references the first second since 1970. This means that <b>5<\/b> represents the fifth second on January 1, 1970.<\/p>\n<p>The Python standard library provides us with tools to get the current time as Unix time and to transform between datetime objects and their <b>int<\/b> representations as Unix time.<\/p>\n<p>Getting the current time as an integer:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">import<\/span> datetime <span style=\"color: #800000; font-weight: bold;\">as<\/span> dt\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">from<\/span> dateutil<span style=\"color: #808030;\">.<\/span>tz <span style=\"color: #800000; font-weight: bold;\">import<\/span> gettz\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">import<\/span> time\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> unix_time <span style=\"color: #808030;\">=<\/span> time<span style=\"color: #808030;\">.<\/span>time<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>Unix time to datetime:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> unix_time\r\n<span style=\"color: #008000;\">1492636231.597816<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> datetime <span style=\"color: #808030;\">=<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>fromtimestamp<span style=\"color: #808030;\">(<\/span>unix_time<span style=\"color: #808030;\">,<\/span> gettz<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/London\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> datetime<span style=\"color: #808030;\">.<\/span>isoformat<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'2017-04-19T22:10:31.597816+01:00'<\/span>\r\n<\/pre>\n<p>Getting the Unix time given a datetime:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> time<span style=\"color: #808030;\">.<\/span>mktime<span style=\"color: #808030;\">(<\/span>datetime<span style=\"color: #808030;\">.<\/span>timetuple<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #008000;\">1492636231.0<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #696969;\"># or using the calendar library<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> calendar<span style=\"color: #808030;\">.<\/span>timegm<span style=\"color: #808030;\">(<\/span>datetime<span style=\"color: #808030;\">.<\/span>timetuple<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<h3>Objects<\/h3>\n<p>The last option is to serialize the object itself as an object that will give special meaning at decoding time:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #800000; font-weight: bold;\">import<\/span> datetime <span style=\"color: #800000; font-weight: bold;\">as<\/span> dt\r\n<span style=\"color: #800000; font-weight: bold;\">from<\/span> dateutil<span style=\"color: #808030;\">.<\/span>tz <span style=\"color: #800000; font-weight: bold;\">import<\/span> gettz<span style=\"color: #808030;\">,<\/span> tzoffset\r\n\r\n<span style=\"color: #800000; font-weight: bold;\">def<\/span> json_to_dt<span style=\"color: #808030;\">(<\/span>obj<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">:<\/span>\r\n    <span style=\"color: #800000; font-weight: bold;\">if<\/span> obj<span style=\"color: #808030;\">.<\/span>pop<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">'__type__'<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #074726;\">None<\/span><span style=\"color: #808030;\">)<\/span> <span style=\"color: #44aadd;\">!=<\/span> <span style=\"color: #0000e6;\">\"datetime\"<\/span><span style=\"color: #808030;\">:<\/span>\r\n        <span style=\"color: #800000; font-weight: bold;\">return<\/span> obj\r\n    zone<span style=\"color: #808030;\">,<\/span> offset <span style=\"color: #808030;\">=<\/span> obj<span style=\"color: #808030;\">.<\/span>pop<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"tz\"<\/span><span style=\"color: #808030;\">)<\/span>\r\n    obj<span style=\"color: #808030;\">[<\/span><span style=\"color: #0000e6;\">\"tzinfo\"<\/span><span style=\"color: #808030;\">]<\/span> <span style=\"color: #808030;\">=<\/span> tzoffset<span style=\"color: #808030;\">(<\/span>zone<span style=\"color: #808030;\">,<\/span> offset<span style=\"color: #808030;\">)<\/span>\r\n    <span style=\"color: #800000; font-weight: bold;\">return<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #44aadd;\">**<\/span>obj<span style=\"color: #808030;\">)<\/span>\r\n\r\n<span style=\"color: #800000; font-weight: bold;\">def<\/span> dt_to_json<span style=\"color: #808030;\">(<\/span>obj<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">:<\/span>\r\n    <span style=\"color: #800000; font-weight: bold;\">if<\/span> <span style=\"color: #400000;\">isinstance<\/span><span style=\"color: #808030;\">(<\/span>obj<span style=\"color: #808030;\">,<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">:<\/span>\r\n        <span style=\"color: #800000; font-weight: bold;\">return<\/span> <span style=\"color: #800080;\">{<\/span>\r\n            <span style=\"color: #0000e6;\">\"__type__\"<\/span><span style=\"color: #808030;\">:<\/span> <span style=\"color: #0000e6;\">\"datetime\"<\/span><span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"year\"<\/span><span style=\"color: #808030;\">:<\/span> obj<span style=\"color: #808030;\">.<\/span>year<span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"month\"<\/span> <span style=\"color: #808030;\">:<\/span> obj<span style=\"color: #808030;\">.<\/span>month<span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"day\"<\/span> <span style=\"color: #808030;\">:<\/span> obj<span style=\"color: #808030;\">.<\/span>day<span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"hour\"<\/span> <span style=\"color: #808030;\">:<\/span> obj<span style=\"color: #808030;\">.<\/span>hour<span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"minute\"<\/span> <span style=\"color: #808030;\">:<\/span> obj<span style=\"color: #808030;\">.<\/span>minute<span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"second\"<\/span> <span style=\"color: #808030;\">:<\/span> obj<span style=\"color: #808030;\">.<\/span>second<span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"microsecond\"<\/span> <span style=\"color: #808030;\">:<\/span> obj<span style=\"color: #808030;\">.<\/span>microsecond<span style=\"color: #808030;\">,<\/span>\r\n            <span style=\"color: #0000e6;\">\"tz\"<\/span><span style=\"color: #808030;\">:<\/span> <span style=\"color: #808030;\">(<\/span>obj<span style=\"color: #808030;\">.<\/span>tzinfo<span style=\"color: #808030;\">.<\/span>tzname<span style=\"color: #808030;\">(<\/span>obj<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">,<\/span> obj<span style=\"color: #808030;\">.<\/span>utcoffset<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>total_seconds<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n        <span style=\"color: #800080;\">}<\/span>\r\n    <span style=\"color: #800000; font-weight: bold;\">else<\/span><span style=\"color: #808030;\">:<\/span>\r\n        <span style=\"color: #800000; font-weight: bold;\">raise<\/span> <span style=\"color: #074726;\">TypeError<\/span><span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Cant serialize {}\"<\/span><span style=\"color: #808030;\">.<\/span>format<span style=\"color: #808030;\">(<\/span>obj<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>Now we can encode JSON:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">import<\/span> json\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> now <span style=\"color: #808030;\">=<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>now<span style=\"color: #808030;\">(<\/span>dt<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">.<\/span>utc<span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> json<span style=\"color: #808030;\">.<\/span>dumps<span style=\"color: #808030;\">(<\/span>now<span style=\"color: #808030;\">,<\/span> default<span style=\"color: #808030;\">=<\/span>dt_to_json<span style=\"color: #808030;\">)<\/span>  <span style=\"color: #696969;\"># From datetime<\/span>\r\n<span style=\"color: #0000e6;\">'{\"__type__\": \"datetime\", \"year\": 2017, \"month\": 4, \"day\": 19, \"hour\": 22, \"minute\": 32, \"second\": 44, \"microsecond\": 778735, \"tz\": \"UTC\"}'<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #696969;\"># Also works with timezones<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> now <span style=\"color: #808030;\">=<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>now<span style=\"color: #808030;\">(<\/span>gettz<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/London\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> json<span style=\"color: #808030;\">.<\/span>dumps<span style=\"color: #808030;\">(<\/span>now<span style=\"color: #808030;\">,<\/span> default<span style=\"color: #808030;\">=<\/span>dt_to_json<span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'{\"__type__\": \"datetime\", \"year\": 2017, \"month\": 4, \"day\": 19, \"hour\": 23, \"minute\": 33, \"second\": 46, \"microsecond\": 681533, \"tz\": \"BST\"}'<\/span>\r\n<\/pre>\n<p>And decode:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> input_json<span style=\"color: #808030;\">=<\/span><span style=\"color: #0000e6;\">'{\"__type__\": \"datetime\", \"year\": 2017, \"month\": 4, \"day\": 19, \"hour\": 23, \"minute\": 33, \"second\": 46, \"microsecond\": 681533, \"tz\": \"BST\"}'<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> json<span style=\"color: #808030;\">.<\/span>loads<span style=\"color: #808030;\">(<\/span>input_json<span style=\"color: #808030;\">,<\/span> object_hook<span style=\"color: #808030;\">=<\/span>json_to_dt<span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">4<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">19<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">23<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">33<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">46<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">681533<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>tzlocal<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> input_json<span style=\"color: #808030;\">=<\/span><span style=\"color: #0000e6;\">'{\"__type__\": \"datetime\", \"year\": 2017, \"month\": 4, \"day\": 19, \"hour\": 23, \"minute\": 33, \"second\": 46, \"microsecond\": 681533, \"tz\": \"EST\"}'<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> json<span style=\"color: #808030;\">.<\/span>loads<span style=\"color: #808030;\">(<\/span>input_json<span style=\"color: #808030;\">,<\/span> object_hook<span style=\"color: #808030;\">=<\/span>json_to_dt<span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">4<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">19<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">23<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">33<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">46<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">681533<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>tzfile<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">'\/usr\/share\/zoneinfo\/EST'<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> json<span style=\"color: #808030;\">.<\/span>loads<span style=\"color: #808030;\">(<\/span>input_json<span style=\"color: #808030;\">,<\/span> object_hook<span style=\"color: #808030;\">=<\/span>json_to_dt<span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>isoformat<span style=\"color: #808030;\">(<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #0000e6;\">'2017-04-19T23:33:46.681533-05:00'<\/span>\r\n<\/pre>\n<h2>Wall times<\/h2>\n<p>After this, you might be tempted to convert all datetime objects to UTC and work only with UTC datetimes and fixed offsets. Even if this is by far the best approach for timestamps, it quickly breaks for future wall times.<\/p>\n<p>We can distinguish two main types of <i>time<\/i> points: wall times and timestamps. Timestamps are universal points in time not related to anywhere in particular. Examples include the time a star is born or when a line is logged to a file. Things change when we speak about the time &#8220;we read on the wall clock.&#8221; When we say &#8220;see you tomorrow at 2,&#8221; we are not referring to UTC offsets, but to tomorrow at 2 PM in our local time zone, no matter what the offset is at this point. We cannot just map those wall times to timestamps (although we can for past ones) because, for future occurrences, countries might change their offset, which happens more frequently than you might think.<\/p>\n<p>For those situations, we need to save the datetime with the time zone to which it refers, and not the offset.<\/p>\n<h2>Differences when working with pytz<\/h2>\n<p>Since Python 3.6, the recommended library to get the Olson database is <b><a href=\"https:\/\/dateutil.readthedocs.io\/en\/stable\/\" target=\"_blank\" rel=\"noopener noreferrer\">dateutil.tz<\/a><\/b>, but it used to be <b><a href=\"https:\/\/pytz.sourceforge.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">pytz<\/a><\/b>.<\/p>\n<p>They might seem similar, but, in some situations, their approaches to handling time zones is quite different. Getting the current time is simple as well:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> <span style=\"color: #800000; font-weight: bold;\">import<\/span> pytz\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">.<\/span>now<span style=\"color: #808030;\">(<\/span>pytz<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/London\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">4<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">20<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">0<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">13<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">26<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">469264<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span><span style=\"color: #44aadd;\">&lt;<\/span>DstTzInfo <span style=\"color: #0000e6;\">'Europe\/London'<\/span> BST<span style=\"color: #44aadd;\">+<\/span><span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span> DST<span style=\"color: #44aadd;\">&gt;<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>A common pitfall with <b>pytz<\/b> it to pass a <b>pytz<\/b> time zone as a <b>tzinfo<\/b> attribute of a datetime:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">5<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span>pytz<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Helsinki\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">5<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">0<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">0<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span><span style=\"color: #44aadd;\">&lt;<\/span>DstTzInfo <span style=\"color: #0000e6;\">'Europe\/Helsinki'<\/span> LMT<span style=\"color: #44aadd;\">+<\/span><span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">40<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span> STD<span style=\"color: #44aadd;\">&gt;<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> pytz<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Helsinki\"<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">.<\/span>localize<span style=\"color: #808030;\">(<\/span>dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">5<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">,<\/span> is_dst<span style=\"color: #808030;\">=<\/span><span style=\"color: #074726;\">None<\/span><span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">5<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">0<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span><span style=\"color: #44aadd;\">&lt;<\/span>DstTzInfo <span style=\"color: #0000e6;\">'Europe\/Helsinki'<\/span> EEST<span style=\"color: #44aadd;\">+<\/span><span style=\"color: #008c00;\">3<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span> DST<span style=\"color: #44aadd;\">&gt;<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>We always should call <b>localize<\/b> on the datetime objects we build. Otherwise, <b>pytz<\/b> will assign the first offset it finds for the time zone.<\/p>\n<p>Another major difference can be found when performing time arithmetic. While we saw that the additions worked in <b>dateutil<\/b> as if we were adding wall time in the specified time zone, when the datetime has a <b>pytz<\/b> <b>tzinfo<\/b> instance, absolute hours are added and the caller must call <b>normalize<\/b> after the operation, as it won&#8217;t handle DST changes. For example:<\/p>\n<pre style=\"color: #000000; background: #ffffff;\"><span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> today <span style=\"color: #808030;\">=<\/span> dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">10<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">29<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> tz <span style=\"color: #808030;\">=<\/span> pytz<span style=\"color: #808030;\">.<\/span>timezone<span style=\"color: #808030;\">(<\/span><span style=\"color: #0000e6;\">\"Europe\/Madrid\"<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> today <span style=\"color: #808030;\">=<\/span> tz<span style=\"color: #808030;\">.<\/span>localize<span style=\"color: #808030;\">(<\/span>dt<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">10<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">29<\/span><span style=\"color: #808030;\">)<\/span><span style=\"color: #808030;\">,<\/span> is_dst<span style=\"color: #808030;\">=<\/span><span style=\"color: #074726;\">None<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> tomorrow <span style=\"color: #808030;\">=<\/span> today <span style=\"color: #44aadd;\">+<\/span> dt<span style=\"color: #808030;\">.<\/span>timedelta<span style=\"color: #808030;\">(<\/span>days<span style=\"color: #808030;\">=<\/span><span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> tomorrow\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">10<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">30<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">0<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">0<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span><span style=\"color: #44aadd;\">&lt;<\/span>DstTzInfo <span style=\"color: #0000e6;\">'Europe\/Madrid'<\/span> CEST<span style=\"color: #44aadd;\">+<\/span><span style=\"color: #008c00;\">2<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span> DST<span style=\"color: #44aadd;\">&gt;<\/span><span style=\"color: #808030;\">)<\/span>\r\n<span style=\"color: #44aadd;\">&gt;&gt;<\/span><span style=\"color: #44aadd;\">&gt;<\/span> tz<span style=\"color: #808030;\">.<\/span>normalize<span style=\"color: #808030;\">(<\/span>tomorrow<span style=\"color: #808030;\">)<\/span>\r\ndatetime<span style=\"color: #808030;\">.<\/span>datetime<span style=\"color: #808030;\">(<\/span><span style=\"color: #008c00;\">2017<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">10<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">29<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">23<\/span><span style=\"color: #808030;\">,<\/span> <span style=\"color: #008c00;\">0<\/span><span style=\"color: #808030;\">,<\/span> tzinfo<span style=\"color: #808030;\">=<\/span><span style=\"color: #44aadd;\">&lt;<\/span>DstTzInfo <span style=\"color: #0000e6;\">'Europe\/Madrid'<\/span> CET<span style=\"color: #44aadd;\">+<\/span><span style=\"color: #008c00;\">1<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span><span style=\"color: #808030;\">:<\/span><span style=\"color: #008c00;\">00<\/span> STD<span style=\"color: #44aadd;\">&gt;<\/span><span style=\"color: #808030;\">)<\/span>\r\n<\/pre>\n<p>Note that with the <b>pytz tzinfo<\/b>, it has added 24 absolute hours (23 hours on the wall time).<\/p>\n<p>The following table shows the way to get either wall\/timestamps arithmetic with both <b>pytz<\/b> and <b>dateutil<\/b>:<\/p>\n\n<\/div>\n<div class='bb-wysiwyg'>\n    \n    <table border=\"1\" cellspacing=\"2\" cellpadding=\"2\">\n<tbody>\n<tr>\n<td><\/td>\n<td style=\"text-align: center;\"><strong>pytz<\/strong><\/td>\n<\/tr>\n<tr>\n<td>wall time<\/td>\n<td>obj.tzinfo.localize(obj.replace(tzinfo=None) + timedelta, is_dst=is_dst)<\/td>\n<\/tr>\n<tr>\n<td>absolute time<\/td>\n<td>obj.tzinfo.normalize(obj + timedelta)<\/td>\n<\/tr>\n<tr>\n<td><\/td>\n<td style=\"text-align: center;\"><strong>dateutil<\/strong><\/td>\n<\/tr>\n<tr>\n<td>wall time<\/td>\n<td>obj + timedelta<\/td>\n<\/tr>\n<tr>\n<td>absolute time<\/td>\n<td>(obj.astimezone(pytz.utc) + timedelta).astimezone(obj.tzinfo)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<\/div>\n<div class='bb-wysiwyg'>\n    \n    <p>Note that adding wall times can lead to unexpected results when DST changes occur.<\/p>\n<p>Finally, <b>dateutil<\/b> plays nicely with the fold attribute added in <a href=\"https:\/\/www.python.org\/dev\/peps\/pep-0495\/\" target=\"_blank\" rel=\"noopener noreferrer\">PEP0495<\/a> and provides backward compatibility if you are using earlier versions of Python.<\/p>\n<h2>Quick tips<\/h2>\n<p>After all this, how should we avoid the common issues when working with time?<\/p>\n<ul>\n<li>Always use time zones. Don&#8217;t rely on implicit local time zones.<\/li>\n<li>Use <b>dateutil<\/b>\/<b>pytz<\/b> to handle time zones.<\/li>\n<li>Always use UTC when working with timestamps.<\/li>\n<li>Remember that, for some time zones, a day is not always made of 24 hours.<\/li>\n<li>Keep your time zone database up to date.<\/li>\n<li>Always test your code against situations such as DST changes.<\/li>\n<\/ul>\n<h2>Libraries worth mentioning<\/h2>\n<ul>\n<li><a href=\"https:\/\/dateutil.readthedocs.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">dateutil<\/a>: Multiple utilities to work with time<\/li>\n<li><a href=\"https:\/\/github.com\/spulec\/freezegun\" target=\"_blank\" rel=\"noopener noreferrer\">freezegun<\/a>: Easier testing of time-related applications<\/li>\n<li><a href=\"https:\/\/arrow.readthedocs.io\/en\/latest\/\" target=\"_blank\" rel=\"noopener noreferrer\">arrow<\/a>\/<a href=\"https:\/\/pendulum.eustace.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">pendulum<\/a>: Drop-in replacement, utilities and extensions for the standard datetime module<\/li>\n<li><a href=\"https:\/\/docs.astropy.org\/en\/stable\/time\/\" target=\"_blank\" rel=\"noopener noreferrer\">astropy<\/a>: Useful for astronomical times and working with leap seconds<\/li>\n<\/ul>\n\n<\/div>\n\n<\/div>\n\n\n\t\t\n\t<\/div>\n<\/div>\n\n","protected":false},"excerpt":{"rendered":"<p>Get a better understanding of datetime in Python with this primer.<\/p>\n","protected":false},"author":313,"featured_media":19344,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1466],"tags":[1464,1481],"class_list":["post-20563","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech-at-bloomberg","tag-open-source","tag-python"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v19.11 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to work with dates and time with Python | Bloomberg LP<\/title>\n<meta name=\"description\" content=\"Get a better understanding of datetime in Python with this primer.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to work with dates and time with Python | Bloomberg LP\" \/>\n<meta property=\"og:description\" content=\"Get a better understanding of datetime in Python with this primer.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/\" \/>\n<meta property=\"og:site_name\" content=\"Bloomberg L.P.\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/bloomberglp\/\" \/>\n<meta property=\"article:published_time\" content=\"2018-05-10T14:40:35+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-11-14T20:42:29+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png\" \/>\n\t<meta property=\"og:image:width\" content=\"520\" \/>\n\t<meta property=\"og:image:height\" content=\"292\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"akelber5\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png\" \/>\n<meta name=\"twitter:creator\" content=\"@bloomberg\" \/>\n<meta name=\"twitter:site\" content=\"@bloomberg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"akelber5\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/\",\"url\":\"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/\",\"name\":\"How to work with dates and time with Python | Bloomberg LP\",\"isPartOf\":{\"@id\":\"https:\/\/www.bloomberg.com\/company\/#website\"},\"datePublished\":\"2018-05-10T14:40:35+00:00\",\"dateModified\":\"2022-11-14T20:42:29+00:00\",\"author\":{\"@id\":\"https:\/\/www.bloomberg.com\/company\/#\/schema\/person\/09c9e1a38b7f345ce5c0b4bbde1656a6\"},\"description\":\"Get a better understanding of datetime in Python with this primer.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":\"1\",\"name\":\"Home\",\"item\":\"https:\/\/www.bloomberg.com\/company\/\"},{\"@type\":\"ListItem\",\"position\":\"2\",\"name\":\"How to work with dates and time with Python\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.bloomberg.com\/company\/#website\",\"url\":\"https:\/\/www.bloomberg.com\/company\/\",\"name\":\"Bloomberg L.P.\",\"description\":\"Bloomberg L.P. is the leader in global business and financial information, enabling customers to make smarter, faster, more informed business decisions.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.bloomberg.com\/company\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.bloomberg.com\/company\/#\/schema\/person\/09c9e1a38b7f345ce5c0b4bbde1656a6\",\"name\":\"Bloomberg L.P.\",\"url\":\"https:\/\/www.bloomberg.com\/company\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to work with dates and time with Python | Bloomberg LP","description":"Get a better understanding of datetime in Python with this primer.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/","og_locale":"en_US","og_type":"article","og_title":"How to work with dates and time with Python | Bloomberg LP","og_description":"Get a better understanding of datetime in Python with this primer.","og_url":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/","og_site_name":"Bloomberg L.P.","article_publisher":"https:\/\/www.facebook.com\/bloomberglp\/","article_published_time":"2018-05-10T14:40:35+00:00","article_modified_time":"2022-11-14T20:42:29+00:00","og_image":[{"width":520,"height":292,"url":"https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png","type":"image\/png"}],"author":"akelber5","twitter_card":"summary_large_image","twitter_image":"https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png","twitter_creator":"@bloomberg","twitter_site":"@bloomberg","twitter_misc":{"Written by":"akelber5","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/","url":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/","name":"How to work with dates and time with Python | Bloomberg LP","isPartOf":{"@id":"https:\/\/www.bloomberg.com\/company\/#website"},"datePublished":"2018-05-10T14:40:35+00:00","dateModified":"2022-11-14T20:42:29+00:00","author":{"@id":"https:\/\/www.bloomberg.com\/company\/#\/schema\/person\/09c9e1a38b7f345ce5c0b4bbde1656a6"},"description":"Get a better understanding of datetime in Python with this primer.","breadcrumb":{"@id":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.bloomberg.com\/company\/stories\/work-dates-time-python\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":"1","name":"Home","item":"https:\/\/www.bloomberg.com\/company\/"},{"@type":"ListItem","position":"2","name":"How to work with dates and time with Python"}]},{"@type":"WebSite","@id":"https:\/\/www.bloomberg.com\/company\/#website","url":"https:\/\/www.bloomberg.com\/company\/","name":"Bloomberg L.P.","description":"Bloomberg L.P. is the leader in global business and financial information, enabling customers to make smarter, faster, more informed business decisions.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.bloomberg.com\/company\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.bloomberg.com\/company\/#\/schema\/person\/09c9e1a38b7f345ce5c0b4bbde1656a6","name":"Bloomberg L.P.","url":"https:\/\/www.bloomberg.com\/company"}]}},"featured_image_rendered":"<img srcset='https:\/\/assets.bbhub.io\/image\/v1\/resize?width=auto&type=webp&url=https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png 520w, https:\/\/assets.bbhub.io\/image\/v1\/resize?width=auto&type=webp&url=https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png 300w, https:\/\/assets.bbhub.io\/image\/v1\/resize?width=auto&type=webp&url=https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png 170w, https:\/\/assets.bbhub.io\/image\/v1\/resize?width=auto&type=webp&url=https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png 140w' src='https:\/\/assets.bbhub.io\/image\/v1\/resize?width=auto&type=webp&url=https:\/\/assets.bbhub.io\/company\/sites\/51\/2018\/05\/clocks_time.png' alt='Image by: Matteo Ianeselli. Modified by Opensource.com. CC-BY-3.0.' \/>","category_info":{"name":"Tech At Bloomberg","blog_landing_name":"Tech At Bloomberg"},"_links":{"self":[{"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/posts\/20563","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/users\/313"}],"replies":[{"embeddable":true,"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/comments?post=20563"}],"version-history":[{"count":3,"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/posts\/20563\/revisions"}],"predecessor-version":[{"id":27621,"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/posts\/20563\/revisions\/27621"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/media\/19344"}],"wp:attachment":[{"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/media?parent=20563"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/categories?post=20563"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.bloomberg.com\/company\/wp-json\/wp\/v2\/tags?post=20563"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}