Movatterモバイル変換


[0]ホーム

URL:


— FREE Email Series —

🐍 Python Tricks 💌

Python Tricks Dictionary Merge

🔒 No spam. Unsubscribe any time.

Browse TopicsGuided Learning Paths
Basics Intermediate Advanced
aialgorithmsapibest-practicescareercommunitydatabasesdata-sciencedata-structuresdata-vizdevopsdjangodockereditorsflaskfront-endgamedevguimachine-learningnewsnumpyprojectspythonstdlibtestingtoolsweb-devweb-scraping

Table of Contents

Recommended Course

Using Python datetime to Work With Dates and Times

Using Python's datetime Module

35m · 6 lessons

Using Python datetime to Work With Dates and Times

Using Python datetime to Work With Dates and Times

byBryan WeberReading time estimate 37mintermediatestdlib

Table of Contents

Remove ads

Recommended Course

Using Python's datetime Module(35m)

Working with dates and times is one of the biggest challenges in programming. Between dealing with time zones, daylight saving time, and different written date formats, it can be tough to keep track of which days and times you’re referencing. Fortunately, the built-in Pythondatetime module can help you manage the complex nature of dates and times.

In this tutorial, you’ll learn:

  • Why programming withdates and times is such a challenge
  • Which functions are available in thePythondatetime module
  • How toprint or read a date and time in a specific format
  • How to doarithmetic with dates and times

Plus, you’re going to develop a neat application to count down the time remaining until the next PyCon US!

Free Bonus:Click here to get our free Python Cheat Sheet that shows you the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.

Let’s get started!

Programming With Dates and Times

If you’ve ever worked on software that needed to keep track of times across several geographic areas, then you probably have a sense of why programming with time can be such a pain. The fundamental disconnect is that computer programs prefer events that are perfectly ordered and regular, but the way in which most humans use and refer to time is highly irregular.

Note: If you want to learn more about why time can be so complicated to deal with, then there are many great resources available on the web. Here are a few good places to start:

One great example of this irregularity isdaylight saving time. In the United States and Canada, clocks are set forward by one hour on the second Sunday in March and set back by one hour on the first Sunday in November. However, this has only been the casesince 2007. Prior to 2007, clocks were set forward on the first Sunday in April and set back on the last Sunday in October.

Things get even more complicated when you considertime zones. Ideally, time zone boundaries would follow lines of longitude exactly. However, for historical and political reasons, time zone lines are rarely straight. Often, areas that are separated by large distances find themselves in the same time zone, and adjacent areas are in different time zones. There are some time zones out there withpretty funky shapes.

How Computers Count Time

Nearly all computers count time from an instant called theUnix epoch. This occurred on January 1, 1970, at 00:00:00 UTC. UTC stands forCoordinated Universal Time and refers to the time at a longitude of 0°. UTC is often also calledGreenwich Mean Time, or GMT. UTC is not adjusted for daylight saving time, so it consistently keeps twenty-four hours in every day.

By definition, Unix time elapses at the same rate as UTC, so a one-second step in UTC corresponds to a one-second step in Unix time. You can usually figure out the date and time in UTC of any given instant since January 1, 1970, by counting the number of seconds since the Unix epoch, with the exception ofleap seconds. Leap seconds are occasionally added to UTC to account for the slowing of the Earth’s rotation but are not added to Unix time.

Note: There’s an interesting bug associated with Unix time. Since many older operating systems are 32-bit, they store the Unix time in a 32-bit signed integer.

This means that at 03:14:07 on January 19, 2038, the integer will overflow, resulting in what’s known as theYear 2038 problem, or Y2038. Similar to theY2K problem, Y2038 will need to be corrected to avoid catastrophic consequences for critical systems.

Nearly all programming languages, includingPython, incorporate the concept of Unix time. Python’s standard library includes a module calledtime that can print the number of seconds since the Unix epoch:

Python
>>>importtime>>>time.time()1579718137.550164

In this example, youimport thetime module and executetime() to print the Unix time, or number of seconds (excluding leap seconds) since the epoch.

In addition to Unix time, computers need a way to convey time information to users. As you saw in the last example, Unix time is nearly impossible for a human to parse. Instead, Unix time is typically converted to UTC, which can then be converted into a local time usingtime zone offsets.

TheInternet Assigned Numbers Authority (IANA) maintains adatabase of all of the values of time zone offsets. IANA also releases regular updates that include any changes in time zone offsets. This database is often included with your operating system, although certain applications may include an updated copy.

The database contains a copy of all the designated time zones and how many hours and minutes they’re offset from UTC. So, during the winter, when daylight saving time is not in effect, the US Eastern time zone has an offset of -05:00, or negative five hours from UTC. Other regions have different offsets, which may not be integer hours. The UTC offset for Nepal, for example, is +05:45, or positive five hours and forty-five minutes from UTC.

How Standard Dates Can Be Reported

Unix time is how computers count time, but it would be incredibly inefficient for humans to determine the time by calculating the number of seconds from an arbitrary date. Instead, we work in terms of years, months, days, and so forth. But even with these conventions in place, another layer of complexity stems from the fact that different languages and cultures have different ways of writing the date.

For instance, in the United States, dates are usually written starting with the month, then the day, then the year. This means that January 31, 2020, is written as01-31-2020. This closely matches the long-form written version of the date.

However, most of Europe and many other areas write the date starting with the day, then the month, then the year. This means that January 31, 2020, is written as31-01-2020. These differences can cause all sorts of confusion when communicating across cultures.

To help avoid communication mistakes, the International Organization for Standardization (ISO) developedISO 8601. This standard specifies that all dates should be written in order of most-to-least-significant data. This means the format is year, month, day, hour, minute, and second:

Text
YYYY-MM-DD HH:MM:SS

In this example,YYYY represents a four-digit year, andMM andDD are the two-digit month and day, starting with a zero if necessary. After that,HH,MM, andSS represent the two-digit hours, minutes, and seconds, starting with a zero if necessary.

The advantage of this format is that the date can be represented with no ambiguity. Dates written asDD-MM-YYYY orMM-DD-YYYY can be misinterpreted if the day is a valid month number. You’ll see a littlelater on how you can use the ISO 8601 format with Pythondatetime.

How Time Should Be Stored in Your Program

Most developers who have worked with time have heard the advice to convert local time to UTC and store that value for later reference. In many cases, especially when you’re storing dates from the past, this is enough information to do any necessary arithmetic.

However, a problem can happen if a user of your program inputs a future date in their local time. Time zone and daylight saving time rules change fairly frequently, as you saw earlier with the 2007 change in daylight saving time for the United States and Canada. If the time zone rules for your user’s location change before the future date that they inputted, then UTC won’t provide enough information to convert back to the correct local time.

Note: There are a number of excellent resources available to help you determine the appropriate way to store time data in your application. Here are a few places to start:

In this case, you need to store the local time, including the time zone, that the user inputted as well as the version of the IANA time zone database that was in effect when the user saved the time. This way, you’ll always be able to convert the local time to UTC. However, this approach won’t always allow you to convert UTC to the correct local time.

Using the Pythondatetime Module

As you can see, working with dates and times in programming can be complicated. Fortunately, you rarely need to implement complicated features from scratch these days since many open-source libraries are available to help out. This is definitely the case in Python, which includes three separate modules in the standard library to work with dates and times:

  1. calendar outputs calendars and provides functions using an idealizedGregorian calendar.
  2. datetime supplies classes for manipulating dates and times.
  3. time provides time-related functions where dates are not needed.

In this tutorial, you’ll focus on using the Pythondatetime module. The main focus ofdatetime is to make it less complicated to access attributes of the object related to dates, times, and time zones. Since these objects are so useful,calendar also returns instances of classes fromdatetime.

time is less powerful and more complicated to use thandatetime. Many functions intime return a specialstruct_time instance. This object has anamed tuple interface for accessing stored data, making it similar to an instance ofdatetime. However, it doesn’t support all of the features ofdatetime, especially the ability to perform arithmetic with time values.

datetime provides three classes that make up the high-level interface that most people will use:

  1. datetime.date is an idealized date that assumes the Gregorian calendar extends infinitely into the future and past. This object stores theyear,month, andday as attributes.
  2. datetime.time is an idealized time that assumes there are 86,400 seconds per day with no leap seconds. This object stores thehour,minute,second,microsecond, andtzinfo (time zone information).
  3. datetime.datetime is a combination of adate and atime. It has all the attributes of both classes.

Creating Pythondatetime Instances

The three classes that represent dates and times indatetime have similarinitializers. They can beinstantiated by passing keyword arguments for each of the attributes, such asyear,date, orhour. You can try the code below to get a sense of how each object is created:

Python
>>>fromdatetimeimportdate,time,datetime>>>date(year=2020,month=1,day=31)datetime.date(2020, 1, 31)>>>time(hour=13,minute=14,second=31)datetime.time(13, 14, 31)>>>datetime(year=2020,month=1,day=31,hour=13,minute=14,second=31)datetime.datetime(2020, 1, 31, 13, 14, 31)

In this code, youimport the three main classes fromdatetime andinstantiate each of them by passing arguments to the constructor. You can see that this code is somewhat verbose, and if you don’t have the information you need asintegers, these techniques can’t be used to createdatetime instances.

Fortunately,datetime provides several other convenient ways to createdatetime instances. These methods don’t require you to use integers to specify each attribute, but instead allow you to use some other information:

  1. date.today() creates adatetime.date instance with the current local date.
  2. datetime.now() creates adatetime.datetime instance with the current local date and time.
  3. datetime.combine() combines instances ofdatetime.date anddatetime.time into a singledatetime.datetime instance.

These three ways of creatingdatetime instances are helpful when you don’t know in advance what information you need to pass into the basic initializers. You can try out this code to see how the alternate initializers work:

Python
>>>fromdatetimeimportdate,time,datetime>>>today=date.today()>>>todaydatetime.date(2020, 1, 24)>>>now=datetime.now()>>>nowdatetime.datetime(2020, 1, 24, 14, 4, 57, 10015)>>>current_time=time(now.hour,now.minute,now.second)>>>datetime.combine(today,current_time)datetime.datetime(2020, 1, 24, 14, 4, 57)

In this code, you usedate.today(),datetime.now(), anddatetime.combine() to create instances ofdate,datetime, andtime objects. Each instance is stored in a differentvariable:

  1. today is adate instance that has only the year, month, and day.
  2. now is adatetime instance that has the year, month, day, hour, minute, second, and microseconds.
  3. current_time is atime instance that has the hour, minute, and second set to the same values asnow.

On the last line, you combine the date information intoday with the time information incurrent_time to produce a newdatetime instance.

Warning:datetime also providesdatetime.utcnow(), which returns an instance ofdatetime at the current UTC. However, the Pythondocumentation recommends against using this method because it doesn’t include any time zone information in the resulting instance.

Usingdatetime.utcnow() may produce somesurprising results when doing arithmetic or comparisons betweendatetime instances. In alater section, you’ll see how to assign time zone information todatetime instances.

Using Strings to Create Pythondatetime Instances

Another way to createdate instances is to use.fromisoformat(). To use this method, you provide astring with the date in the ISO 8601 format that you learned aboutearlier. For instance, you might provide a string with the year, month, and date specified:

Text
2020-01-31

This string represents the date January 31, 2020, according to the ISO 8601 format. You can create adate instance with the following example:

Python
>>>fromdatetimeimportdate>>>date.fromisoformat("2020-01-31")datetime.date(2020, 1, 31)

In this code, you usedate.fromisoformat() to create adate instance for January 31, 2020. This method is very useful because it’s based on the ISO 8601 standard. But what if you have a string that represents a date and time but isn’t in the ISO 8601 format?

Fortunately, Pythondatetime provides a method called.strptime() to handle this situation. This method uses a specialmini-language to tell Python which parts of the string are associated with thedatetime attributes.

To construct adatetime from a string using.strptime(), you have to tell Python what each of the parts of the string represents using formatting codes from the mini-language. You can try this example to see how.strptime() works:

Python
 1>>>date_string="01-31-2020 14:45:37" 2>>>format_string="%m-%d-%Y %H:%M:%S"

Online 1, you createdate_string, which represents the date and time January 31, 2020, at 2:45:37 PM. Online 2, you createformat_string, which uses the mini-language to specify how the parts ofdate_string will be turned intodatetime attributes.

Informat_string, you include several formatting codes and all of the dashes (-), colons (:), and spaces exactly as they appear indate_string. To process the date and time indate_string, you include the following formatting codes:

ComponentCodeValue
Year (as four-digit integer )%Y2020
Month (as zero-padded decimal)%m01
Date (as zero-padded decimal)%d31
Hour (as zero-padded decimal with 24-hour clock)%H14
Minute (as zero-padded decimal)%M45
Second (as zero-padded decimal)%S37

A complete listing of all of the options in the mini-language is outside the scope of this tutorial, but you can find several good references on the web, including in Python’sdocumentation and on a website calledstrftime.org.

Now thatdate_string andformat_string are defined, you can use them to create adatetime instance. Here’s an example of how.strptime() works:

Python
 3>>>fromdatetimeimportdatetime 4>>>datetime.strptime(date_string,format_string) 5datetime.datetime(2020, 1, 31, 14, 45, 37)

In this code, you importdatetime online 3 and usedatetime.strptime() withdate_string andformat_string online 4. Finally,line 5 shows the values of the attributes in thedatetime instance created by.strptime(). You can see that they match the values shown in the table above.

Note: There are more advanced ways to createdatetime instances, but they involve using third-party libraries that must be installed. One particularly neat library is calleddateparser, which allows you to provide natural language string inputs. The input is even supported in a number of languages:

Python
 1>>>importdateparser 2>>>dateparser.parse("yesterday") 3datetime.datetime(2020, 3, 13, 14, 39, 1, 350918) 4>>>dateparser.parse("morgen") 5datetime.datetime(2020, 3, 15, 14, 39, 7, 314754)

In this code, you usedateparser to create twodatetime instances by passing two different string representations of time. Online 1, you importdateparser. Then, online 2, you use.parse() with the argument"yesterday" to create adatetime instance twenty-four hours in the past. At the time of writing, this was March 13, 2020, at 2:39 PM.

Online 3, you use.parse() with the argument"morgen".Morgen is the German word for tomorrow, sodateparser creates adatetime instance twenty-four hours in the future. At the time of writing, this was March 15 at 2:39 PM.

Starting Your PyCon Countdown

Now you have enough information to start working on a countdown clock for next year’sPyCon US! PyCon US 2021 will start on May 12, 2021 in Pittsburgh, PA. With the 2020 eventhaving been canceled, many Pythonistas are extra excited for next year’s gathering. This is a great way to keep track of how long you’ll need to wait and boost yourdatetime skills at the same time!

To get started, create a file calledpyconcd.py and add this code:

Python
# pyconcd.pyfromdatetimeimportdatetimePYCON_DATE=datetime(year=2021,month=5,day=12,hour=8)countdown=PYCON_DATE-datetime.now()print(f"Countdown to PyCon US 2021:{countdown}")

In this code, you importdatetime fromdatetime and define a constant,PYCON_DATE, that stores the date of the next PyCon US. You don’t expect the date of PyCon to change, so you name the variable in all caps to indicate that it’s a constant.

Next, you compute the difference betweendatetime.now(), which is thecurrent time, andPYCON_DATE. Taking the difference between twodatetime instances returns adatetime.timedelta instance.

timedelta instances represent the change in time between twodatetime instances. Thedelta in the name is a reference to the Greek letter delta, which is used in science and engineering to mean a change. You’ll learn morelater about how to usetimedelta for more general arithmetic operations.

Finally the printed output, as of April 9, 2020 at a little before 9:30 PM is:

Text
Countdown to PyCon US 2021: 397 days, 10:35:32.139350

Only 397 days until PyCon US 2021! This output is a little clunky, solater on you’ll see how you can improve the formatting. If you run this script on a different day, you’ll get a different output. If you run the script after May 12, 2021 at 8:00 AM, you’ll get a negative amount of time remaining!

Working With Time Zones

As you saw earlier, storing the time zone in which a date occurs is an important aspect of ensuring your code is correct. Pythondatetime providestzinfo, which is an abstract base class that allowsdatetime.datetime anddatetime.time to include time zone information, including an idea of daylight saving time.

However,datetime does not provide a direct way to interact with the IANA time zone database. The Pythondatetime.tzinfo documentationrecommends using a third-party package calleddateutil. You can installdateutil withpip:

Shell
$python-mpipinstallpython-dateutil

Note that the name of the package that you install from PyPI,python-dateutil, is different from the name that you use to import the package, which is justdateutil.

Usingdateutil to Add Time Zones to Pythondatetime

One reason thatdateutil is so useful is that it includes an interface to the IANA time zone database. This takes the hassle out of assigning time zones to yourdatetime instances. Try out this example to see how to set adatetime instance to have your local time zone:

Python
>>>fromdateutilimporttz>>>fromdatetimeimportdatetime>>>now=datetime.now(tz=tz.tzlocal())>>>nowdatetime.datetime(2020, 1, 26, 0, 55, 3, 372824, tzinfo=tzlocal())>>>now.tzname()'Eastern Standard Time'

In this example, youimporttz fromdateutil anddatetime fromdatetime. You then create adatetime instance set to the current time using.now().

You also pass thetz keyword to.now() and settz equal totz.tzlocal(). Indateutil,tz.tzlocal() returns a concrete instance ofdatetime.tzinfo. This means that it can represent all the necessary time zone offset and daylight saving time information thatdatetime needs.

You also print the name of the time zone using.tzname(), which prints'Eastern Standard Time'. This is the output for Windows, but on macOS or Linux, your output might read'EST' if you’re in the US Eastern time zone during the winter.

You can also create time zones that are not the same as the time zone reported by your computer. To do this, you’ll usetz.gettz() and pass the officialIANA name for the time zone you’re interested in. Here’s an example of how to usetz.gettz():

Python
>>>fromdateutilimporttz>>>fromdatetimeimportdatetime>>>London_tz=tz.gettz("Europe/London")>>>now=datetime.now(tz=London_tz)>>>nowdatetime.datetime(2020, 1, 26, 6, 14, 53, 513460, tzinfo=tzfile('GB-Eire'))>>>now.tzname()'GMT'

In this example, you usetz.gettz() to retrieve the time zone information for London, United Kingdom and store it inLondon_tz. You then retrieve the current time, setting the time zone toLondon_tz.

On Windows, this gives thetzinfo attribute the valuetzfile('GB-Eire'). On macOS or Linux, thetzinfo attribute will look something liketzfile('/usr/share/zoneinfo/Europe/London), but it might be slightly different depending on wheredateutil pulls the time zone data from.

You also usetzname() to print the name of the time zone, which is now'GMT', meaning Greenwich Mean Time. This output is the same on Windows, macOS, and Linux.

In an earliersection, you learned that you shouldn’t use.utcnow() to create adatetime instance at the current UTC. Now you know how to usedateutil.tz to supply a time zone to thedatetime instance. Here’s an example modified from therecommendation in the Python documentation:

Python
>>>fromdateutilimporttz>>>fromdatetimeimportdatetime>>>datetime.now(tz=tz.UTC)datetime.datetime(2020, 3, 14, 19, 1, 20, 228415, tzinfo=tzutc())

In this code, you usetz.UTC to set the time zone ofdatetime.now() to the UTC time zone. This method is recommended over usingutcnow() becauseutcnow() returns anaivedatetime instance, whereas the method demonstrated here returns anawaredatetime instance.

Next, you’ll take a small detour to learn aboutnaive vsawaredatetime instances. If you already know all about this, then you canskip ahead to improve your PyCon countdown with time zone information.

Comparing Naive and Aware Pythondatetime Instances

Pythondatetime instances support two types of operation, naive and aware. The basic difference between them is that naive instances don’t contain time zone information, whereas aware instances do. More formally, to quote the Python documentation:

An aware object represents a specific moment in time that is not open to interpretation. A naive object does not contain enough information to unambiguously locate itself relative to other date/time objects. (Source)

This is an important distinction for working with Pythondatetime. Anawaredatetime instance can compare itself unambiguously to other awaredatetime instances and will always return the correct time interval when used in arithmetic operations.

Naivedatetime instances, on the other hand, may be ambiguous. One example of this ambiguity relates to daylight saving time. Areas that practice daylight saving time turn the clocks forward one hour in the spring and backward one hour in the fall. This typically happens at 2:00 AM local time. In the spring, the hour from 2:00 AM to 2:59 AMnever happens, and in the fall, the hour from 1:00 AM to 1:59 AM happenstwice!

Practically, what happens is that the offset from UTC in these time zones changes throughout the year. IANA tracks these changes and catalogs them in the different database files that your computer has installed. Using a library likedateutil, which uses the IANA database under the hood, is a great way to make sure that your code properly handles arithmetic with time.

Note: In Python, the difference between naive and awaredatetime instances is determined by thetzinfo attribute. An awaredatetime instance has thetzinfo attribute equal to a subclass of thedatetime.tzinfo abstract base class.

Python 3.8 and below provide one concrete implementation oftzinfo calledtimezone. However,timezone is limited to expressing fixed offsets from UTC that cannot change throughout the year, so it isn’t that useful when you need to account for changes such as daylight saving time.

Python 3.9 includes a new module calledzoneinfo that provides a concrete implementation oftzinfo that tracks the IANA database, so it includes changes like daylight saving time. However, until Python 3.9 becomes widely used, it probably makes sense to rely ondateutil if you need to support multiple Python versions.

dateutil also provides several concrete implementations oftzinfo in thetz module that you used earlier. You can check out thedateutil.tz documentation for more information.

This doesn’t mean that you always need to use awaredatetime instances. But aware instances are crucial if you’re comparing times with each other, especially if you’re comparing times in different parts of the world.

Improving Your PyCon Countdown

Now that you know how to add time zone information to a Pythondatetime instance, you can improve your PyCon countdown code. Earlier, you used the standarddatetime constructor to pass the year, month, day, and hour that PyCon will start. You can update your code to use thedateutil.parser module, which provides a more natural interface for creatingdatetime instances:

Python
# pyconcd.pyfromdateutilimportparser,tzfromdatetimeimportdatetimePYCON_DATE=parser.parse("May 12, 2021 8:00 AM")PYCON_DATE=PYCON_DATE.replace(tzinfo=tz.gettz("America/New_York"))now=datetime.now(tz=tz.tzlocal())countdown=PYCON_DATE-nowprint(f"Countdown to PyCon US 2021:{countdown}")

In this code, youimportparser andtz fromdateutil anddatetime fromdatetime. Next, you useparser.parse() to read the date of the next PyCon US from a string. This is much more readable than the plaindatetime constructor.

parser.parse() returns a naivedatetime instance, so you use.replace() to change thetzinfo to theAmerica/New_York time zone. PyCon US 2021 will take place in Pittsburgh, Pennsylvania, which is in the US Eastern time zone. The canonical name for that time zone isAmerica/New_York since New York City is the largest city in the time zone.

PYCON_DATE is an awaredatetime instance with the time zone set to US Eastern time. Since May 12 is after daylight saving time takes effect, the time zone name is'EDT', or'Eastern Daylight Time'.

Next, you createnow to represent the current instant of time and give it your local time zone. Last, you find thetimedelta betweenPYCON_DATE andnow and print the result. If you’re in a locale that does not adjust the clocks for daylight saving time, then you may see the number of hours remaining until PyCon change by an hour.

Doing Arithmetic With Pythondatetime

Pythondatetime instances support several types of arithmetic. As you saw earlier, this relies on usingtimedelta instances to represent time intervals.timedelta is very useful because it’s built into the Python standard library. Here’s an example of how to work withtimedelta:

Python
>>>fromdatetimeimportdatetime,timedelta>>>now=datetime.now()>>>nowdatetime.datetime(2020, 1, 26, 9, 37, 46, 380905)>>>tomorrow=timedelta(days=+1)>>>now+tomorrowdatetime.datetime(2020, 1, 27, 9, 37, 46, 380905)

In this code, you createnow, which stores the current time, andtomorrow, which is atimedelta of+1 days. Next, you addnow andtomorrow to produce adatetime instance one day in the future. Note that working with naivedatetime instances, as you are here, means that theday attribute of thedatetime increments by one and does not account for any repeated or skipped time intervals.

timedelta instances also support negative values as the input to the arguments:

Python
>>>yesterday=timedelta(days=-1)>>>now+yesterdaydatetime.datetime(2020, 1, 25, 9, 37, 46, 380905)

In this example, you provide-1 as the input totimedelta, so when you addnow andyesterday, the result is a decrease by one in thedays attribute.

timedelta instances support addition and subtraction as well as positive and negative integers for all arguments. You can even provide a mix of positive and negative arguments. For instance, you might want to add three days and subtract four hours:

Python
>>>delta=timedelta(days=+3,hours=-4)>>>now+deltadatetime.datetime(2020, 1, 29, 5, 37, 46, 380905)

In this example, you add three days and subtract four hours, so the newdatetime is at January 29 at 5:37 AM.timedelta is very useful in this way, but it’s somewhat limited because it cannot add or subtract intervals larger than a day, such as a month or a year. Fortunately,dateutil provides a more powerful replacement calledrelativedelta.

The basic syntax ofrelativedelta is very similar totimedelta. You can provide keyword arguments that produce changes of any number of years, months, days, hours, seconds, or microseconds. You can reproduce the firsttimedelta example with this code:

Python
>>>fromdateutil.relativedeltaimportrelativedelta>>>tomorrow=relativedelta(days=+1)>>>now+tomorrowdatetime.datetime(2020, 1, 27, 9, 37, 46, 380905)

In this example, you userelativedelta instead oftimedelta to find thedatetime corresponding to tomorrow. Now you can try adding five years, one month, and three days tonow while subtracting four hours and thirty minutes:

Python
>>>delta=relativedelta(years=+5,months=+1,days=+3,hours=-4,minutes=-30)>>>now+deltadatetime.datetime(2025, 3, 1, 5, 7, 46, 380905)

Notice in this example that the date ends up as March 1, 2025. This is because adding three days tonow would be January 29, and adding one month to that would be February 29, which only exists in a leap year. Since 2025 is not a leap year, the date rolls over to the next month.

You can also userelativedelta to calculate the difference between twodatetime instances. Earlier, you used the subtraction operator to find the difference between two Pythondatetime instances,PYCON_DATE andnow. Withrelativedelta, instead of using the subtraction operator, you need to pass the twodatetime instances as arguments :

Python
>>>nowdatetime.datetime(2020, 1, 26, 9, 37, 46, 380905)>>>tomorrow=datetime(2020,1,27,9,37,46,380905)>>>relativedelta(now,tomorrow)relativedelta(days=-1)

In this example, you create a newdatetime instance fortomorrow by incrementing thedays field by one. Then, you userelativedelta and passnow andtomorrow as the two arguments.dateutil then takes the difference between these twodatetime instances and returns the result as arelativedelta instance. In this case, the difference is-1 days, sincenow happens beforetomorrow.

dateutil.relativedelta objects have countless other uses. You can use them to find complex calendar information, such as the next year in which October the 13th falls on a Friday or what the date will be on the last Friday of the current month. You can even use them to replace attributes of adatetime instance and create, for example, adatetime one week in the future at 10:00 AM. You can read all about these other uses in thedateutildocumentation.

Finishing Your PyCon Countdown

You now have enough tools in your belt to finish your PyCon 2021 countdown clock and provide a nice interface to use as well. In this section, you’ll userelativedelta to calculate the time remaining until PyCon, develop a function to print the time remaining in a nice format, and show the date of PyCon to the user.

Usingrelativedelta in Your PyCon Countdown

First, replace the plain subtraction operator withrelativedelta. With the subtraction operator, yourtimedelta object couldn’t count intervals of time larger than a day. However,relativedelta allows you to show the years, months, and days remaining:

Python
 1# pyconcd.py 2 3fromdateutilimportparser,tz 4fromdateutil.relativedeltaimportrelativedelta 5fromdatetimeimportdatetime 6 7PYCON_DATE=parser.parse("May 12, 2021 8:00 AM") 8PYCON_DATE=PYCON_DATE.replace(tzinfo=tz.gettz("America/New_York")) 9now=datetime.now(tz=tz.tzlocal())1011countdown=relativedelta(PYCON_DATE,now)12print(f"Countdown to PyCon US 2021:{countdown}")

The only change that you made in this code was to replaceline 11 withcountdown = relativedelta(PYCON_DATE, now). The output from this script should tell you that PyCon US 2021 will happen in about one year and one month, depending on when you run the script.

However, that output isn’t very pretty since it looks like the signature ofrelativedelta(). You can build up some prettier output by replacingline 11 in the previous code with the code below:

Python
11deftime_amount(time_unit:str,countdown:relativedelta)->str:12t=getattr(countdown,time_unit)13returnf"{t}{time_unit}"ift!=0else""1415countdown=relativedelta(PYCON_DATE,now)16time_units=["years","months","days","hours","minutes","seconds"]17output=(tfortuintime_unitsif(t:=time_amount(tu,countdown)))18print("Countdown to PyCon US 2021:",", ".join(output))

This code requires Python 3.8 because it uses the newwalrus operator. You can make this script work on older versions of Python by using a traditionalfor loop in place ofline 17.

In this code, you definetime_amount(), which takes two arguments, the unit of time and therelativedelta instance from which the time units should be retrieved. If the amount of time is not equal to zero, thentime_amount() returns a string with the amount of time and the time unit. Otherwise, it returns an empty string.

You usetime_amount() in thecomprehension online 17. That line creates agenerator storing the non-empty strings returned fromtime_amount(). It uses thewalrus operator to assign the return value oftime_amount() tot and includest only if it isTrue.

Finally,line 18 prints the final output using.join() on thegenerator. Next, you’ll take a look at including the PyCon date in the output from your script.

Showing the PyCon Date in Your PyCon Countdown

Earlier, you learned about creatingdatetime instances using.strptime(). This method uses a special mini-language within Python to specify how the date string is formatted.

Pythondatetime has an additional method called.strftime() that allows you to format adatetime instance to a string. In a sense, it’s the reverse operation of parsing using.strptime(). You can differentiate between the two methods by remembering that thep in.strptime() stands forparse, and thef in.strftime() stands forformat.

In your PyCon countdown, you can use.strftime() to print output to let the user know the date on which PyCon US will start. Remember, you can find the formatting codes that you want to use onstrftime.org. Now add this code online 18 of your PyCon countdown script:

Python
18pycon_date_str=PYCON_DATE.strftime("%A, %B%d, %Y at %H:%M %p %Z")19print(f"PyCon US 2021 will start on:",pycon_date_str)20print("Countdown to PyCon US 2021:",", ".join(output))

In this code,line 18 uses.strftime() to create a string representing the starting date of PyCon US 2021. The output includes the weekday, month, day, year, hour, minute, AM or PM, and time zone:

Text
Wednesday, May 12, 2021 at 08:00 AM EDT

Online 19, you print this string for the user to see with some explanatory text. The last line prints the amount of time remaining until the PyCon start date. Next, you’ll finish your script to make it easier for other people to reuse.

Finalizing Your PyCon Countdown

The final step that you’ll want take is to follow Pythonbest practices and put the code that produces output into amain() function. You can check out the full, final code after applying all these changes:

Python
 1# pyconcd.py 2 3fromdateutilimportparser,tz 4fromdateutil.relativedeltaimportrelativedelta 5fromdatetimeimportdatetime 6 7PYCON_DATE=parser.parse("May 12, 2021 8:00 AM") 8PYCON_DATE=PYCON_DATE.replace(tzinfo=tz.gettz("America/New_York")) 910deftime_amount(time_unit:str,countdown:relativedelta)->str:11t=getattr(countdown,time_unit)12returnf"{t}{time_unit}"ift!=0else""1314defmain():15now=datetime.now(tz=tz.tzlocal())16countdown=relativedelta(PYCON_DATE,now)17time_units=["years","months","days","hours","minutes","seconds"]18output=(tfortuintime_unitsif(t:=time_amount(tu,countdown)))19pycon_date_str=PYCON_DATE.strftime("%A, %B%d, %Y at %H:%M %p %Z")20print(f"PyCon US 2021 will start on:",pycon_date_str)21print("Countdown to PyCon US 2021:",", ".join(output))2223if__name__=="__main__":24main()

In this code, you moveprint() and the code used for the generator intomain(). Online 23, you use theguard clause to make sure thatmain() only runs when this file is executed as ascript. This allows other people to import your code and reusePYCON_DATE, for instance, if they’d like.

Now you can modify this script as much as you want. One neat thing to do might be to allow the user to change the time zone associated withnow by passing acommand-line argument. You could also change thePYCON_DATE to something closer to home, sayPyCon Africa orEuroPython.

To get even more excited about PyCon, check outReal Python at PyCon US 2019 andHow to Get the Most Out of PyCon!

Alternatives to Pythondatetime anddateutil

Pythondatetime anddateutil are a powerful combination of libraries when you’re working with dates and times.dateutil is even recommended in the Python documentation. However, there are many other libraries that you can use to work with dates and times in Python. Some of these rely ondatetime anddateutil, while others are completely independent replacements:

  • pytz provides time zone information similar todateutil. It uses a somewhat different interface than the standarddatetime.tzinfo, so be aware of thepotential problems if you decide to use it.
  • Arrow provides a drop-in replacement fordatetime. It’s inspired bymoment.js, so if you’re coming from web development, then this might be a more familiar interface.
  • Pendulum provides another drop-in replacement fordatetime. It includes a time zone interface and an improvedtimedelta implementation.
  • Maya provides a similar interface asdatetime. It relies on Pendulum for parts of the parsing library.
  • dateparser provides an interface to generatedatetime instances from human-readable text. It’s flexible and supports many languages.

In addition, if you work heavily withNumPy,Pandas, or otherdata science packages, then there are a few options that might be useful to you:

  • NumPy provides a similar API to the built-in Pythondatetime library, but the NumPy version can be used in arrays.
  • Pandas provides support for time-series data inDataFrames, usually sequential values of time-based events, by using the NumPydatetime module.
  • cftime provides support for calendars other than theproleptic Gregorian calendar as well as other time units conforming to the Climate and Forecasting (CF) conventions. It’s used by thexarray package to provide time-series support.

Further Reading

Since programming with time can be so complicated, there are many resources on the web to help you learn more about it. Fortunately, this is a problem that many people who work in every programming language have thought about, so you can usually find information or tools to help with any problem you may have. Here’s a selected list of articles and videos that I found helpful in writing this tutorial:

In addition, Paul Ganssle is a core contributor to CPython and the current maintainer ofdateutil. His articles and videos are a great resource for Python users:

Conclusion

In this tutorial, you learned about programming with dates and times and why it often leads to errors and confusion. You also learned about the Pythondatetime anddateutil modules as well as how to work with time zones in your code.

Now you can:

  • Store dates in a good, future-proof format in your programs
  • Create Pythondatetime instances with formatted strings
  • Add time zone information todatetime instances withdateutil
  • Perform arithmetic operations withdatetime instances usingrelativedelta

In the end, you created a script that counts down the time remaining until the next PyCon US so you can get excited for the biggest Python gathering around. Dates and times can be tricky, but with these Python tools in your arsenal, you’re ready to tackle the toughest problems!

Recommended Course

Using Python's datetime Module(35m)

🐍 Python Tricks 💌

Get a short & sweetPython Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

AboutBryan Weber

Bryan is a core developer of Cantera, the open-source platform for thermodynamics, chemical kinetics, and transport. As a developer generalist, Bryan does Python from the web to data science and everywhere inbetween.

» More about Bryan

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

MasterReal-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

MasterReal-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students.Get tips for asking good questions andget answers to common questions in our support portal.


Looking for a real-time conversation? Visit theReal Python Community Chat or join the next“Office Hours” Live Q&A Session. Happy Pythoning!

Keep Learning

Related Topics:intermediatestdlib

Related Learning Paths:

Related Courses:

Related Tutorials:

Keep reading Real Python by creating a free account or signing in:

Already have an account?Sign-In

Almost there! Complete this form and click the button below to gain instant access:

Python Logo

Get the Python Cheat Sheet (Free PDF)

🔒 No spam. We take your privacy seriously.


[8]ページ先頭

©2009-2026 Movatter.jp