Python: Formatting dates and times
Tags: beginners, python, learning, tutorial
Published: 2020-07-07 21:37:44

---
title: Python: Formatting dates and times
published: true
description: How to format dates, times, and datetimes in Python
tags: beginners, python, learning, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/tmz37zlzfjagy9hss6p9.jpg
---

Formatting dates and times into human-readable strings is a common programming task, and Python has a comprehensive method for doing so.

Let's begin by importing the `datetime` and `tz` (timezone) libraries:

```
>>> import datetime
>>> from dateutil import tz
```

The [`datetime` library](https://docs.python.org/3/library/datetime.html) has many useful (and advanced) classes and methods, but exploring them is beyond the scope of this article. To explore formatting dates and times in Python, we will begin by generating a specific datetime, far out in the future. This will provide us with uniquely recognizable string components in our examples below.

Python `datetime` objects contain the following information, in order: `Year`, `Month`, `Day`, `Hour`, `Minute`, `Second`, `Millisecond`, and `Timezone`. Let's generate the datetime for May 4, 9876, at exactly 1.001 seconds after 3:02AM, in Los Angeles. :
```
>>> location = tz.gettz('America/Los_Angeles')
>>> dt = datetime.datetime(9876, 5, 4, 3, 2, 1, 1, tzinfo=location)
```

To format our datetime, we use its `strftime()` method. Let's try a few examples.

### Dates

Let's format our date per the [ISO 8601 standard](https://en.wikipedia.org/wiki/ISO_8601), which is my [personal favorite](https://dev.to/adamlombard/macos-run-a-script-in-any-app-via-custom-hotkey-4n99) and takes the form "YYYY-MM-DD":

```
>>> dt.strftime("%Y-%m-%d")
'9876-05-04'
```

You may notice that the formatting is controlled by characters preceded with a `%`. These are called "directives", and allow us to declare formatting for specific parts of the date and time, while mixing in other plaintext characters, like `-`. There is a reference chart of most `strftime()` directives at the end of this article.

Let's try another. In many parts of the world, it's common to format dates as "DD.MM.YY":
```
>>> dt.strftime("%d.%m.%y")
'04.05.76'
```
(You may notice that the lowercase `y` directive yields a two-character year, instead of the four-character year yielded by the uppercase `Y` directive.)

Finally, let's try a format like "Weekday Name, Month Name (Abbreviated) Date, Year":
```
>>> dt.strftime("%A, %b %d, %Y")
'Thursday, May 04, 9876'
```

### Times

Now we'll format the time.

First, let's try 24-hour time, like "HH:MM:SS":
```
>>> dt.strftime("%H:%M:%S")
'03:02:01'
```

And let's also do 12-hour time, without seconds, showing whether it's AM or PM:
```
>>> dt.strftime("%-I:%M%p")
'3:02AM'
```

### Directives

By mixing and matching the directives below, we can now freely format dates and times in Python:

(NOTE: _Python implements `strftime()` by calling `strftime()` in the platform's C library. Not all directives are available on all platforms, and some platforms may have directives not shown here. These directives were tested in Python 3.8 on macOS 10.15.4._)


#### Dates
|Directive|Meaning|Example|
|---|---|---:|
|`%C`|Century as a 2-digit decimal number (00-99).|98|
|`%Y`|Year (with century) as a decimal number (0001-9999).|9876|
|`%G`|ISO 8601 week-based year (with century) as a decimal number (0001-9999). Represents the year that contains the greater part of the ISO week. See `%V`.|9876|
|`%y`|Year (without century) as a zero-padded decimal number (00-99).|76|
|`%g`|ISO 8601 week-based year (without century) as a decimal number (00-99).|76|
|`%m`|Month as a zero-padded decimal number (01-12).|05|
|`%-m`|Month as a decimal number (1-12).|5|
|`%B`|Locale's full month name.|May|
|`%b`|Locale's abbreviated month name.|May|
|`%h`|Equivalent to `%b`.|May|
|`%d`|Day of the month as a zero-padded decimal number (01-31).|04|
|`%e`|Day of the month as a space-padded decimal number ( 1-31).|' 4'|
|`%-d`|Day of the month as a decimal number (1-31).|4|
|`%j`|Day of the year as a zero-padded decimal number (001-366).|125|
|`%-j`|Day of the year as a decimal number (1-366).|125|
|`%w`|Weekday as a decimal number, where Sunday is `0` and the first day of the week (0-6).|4|
|`%u`|Weekday as a decimal number, where Monday is `1` and the first day of the week (1-7).|4|
|`%A`|Locale's full weekday name.|Thursday|
|`%a`|Locale's abbreviated weekday name.|Thu|
|`%U`|Week of the year as a zero-padded decimal number. Treats Sunday as the first day of the week. All days in a new year preceding the first Sunday are considered to be in week 0. (00-53)|18|
|`%W`|Week of the year as a zero-padded decimal number. Treats Monday as the first day of the week. All days in a new year preceding the first Monday are considered to be in week 0. (00-53)|18|
|`%V`|ISO 8601 week of the year as a zero-padded decimal number. Treats Monday as the first day of the week. Week `01` is the week containing Jan 4. (01-53)|18|

### Times
|Directive|Meaning|Example|
|---|---|---:|
|`%H`|Hour (24-hour clock) as a zero-padded decimal number (00-23).|03|
|`%k`|Hour (24-hour clock) as a space-padded decimal number ( 0-23).|' 3'|
|`%-H`|Hour (24-hour clock) as a decimal number (0-23).|3|
|`%I`|Hour (12-hour clock) as a zero-padded decimal number (01-12).|03|
|`%l`|Hour (12-hour clock) as a space-padded decimal number ( 1-12).|' 3'|
|`%-I`|Hour (12-hour clock) as a decimal number (1-12).|3|
|`%M`|Minute as a zero-padded decimal number (00-59).|02|
|`%-M`|Minute as a decimal number (0-59).|2|
|`%S`|Second as a zero-padded decimal number (00-59).|01|
|`%-S`|Second as a decimal number (0-59).|1|
|`%f`|Millisecond as a six-digit, zero-padded decimal number (000000-999999).|000001|
|`%p`|Locale's equivalent of either AM or PM.|AM|
|`%z`|Locale's UTC offset in the form `±HHMM[SS[.ffffff]]`. Empty string if the object is naive.|-0800|
|`%Z`|Locale's time zone name.|PST|

### Short Codes
|Directive|Meaning|Example|
|---|---|---:|
|`%c`|Locale's preferred date and time representation.|Thu May  4 03:02:01 9876|
|`%D`|Equivalent to `%m/%d/%y`.|5/04/76|
|`%F`|Equivalent to `%Y-%m-%d` (the ISO 8601 format).|9876-05-04|
|`%r`|Time in locale's preferred AM or PM notation.|03:02:01 AM|
|`%R`|Time in 24-hour notation (without seconds). Equivalent to `%H:%M`.|03:02|
|`%T`|Time in 24-hour notation (with seconds). Equivalent to `%H:%M:%S`.|03:02:01|
|`%x`|Locale's preferred date representation (without time).|05/04/76|
|`%X`|Locale's preferred time representation (without date).|03:02:01|

### Misc
|Directive|Meaning|Example|
|---|---|---:|
|`%%`|A literal `%` character.|%|
|`%n`|A newline character.||
|`%t`|A tab character.||
|`%s`|The number of seconds since the [Unix Epoch](https://en.wikipedia.org/wiki/Unix_time): `1970-01-01 00:00:00 +0000 (UTC)`|249499998121|

---
[Documentation for `strftime()`.](https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior)

---

Was this helpful? Did I save you some time?

## {% cta https://www.adamlombard.com/support-me %} 🫖 Buy Me A Tea! ☕️ {% endcta %}

---