2.2. Datetime Parsing and Formatting

2.2.1. Date formats

2.2.1.1. Date format in USA

Listing 2.47. Formal date format in USA [Wik19d]
4/12/61
April 12, 1961

2.2.1.2. Date format in Japan

Listing 2.48. Formal date format in Japan [Wik19c]
20/12/31

2.2.1.3. Date format in Germany

Listing 2.49. Formal date format in Germany
12.04.1961

2.2.1.4. Date format in Poland

12.4.1961
12.04.1961

12 IV 1961
12.IV.1961

12/4/1961
12/04/1961

12 kwietnia 1961
12 kwiecień 1961

2.2.2. Time formats

2.2.2.1. 24 and 12 hour clock

  • What AM stands for?

  • What PM stands for?

17:00
5:00 PM

2.2.2.2. Noon and Midnight

  • Which time is a midnight?

  • Which time is a noon?

  • Confusion at noon and midnight

  • Is 12:00 a noon (in 24h format), or someone just simply forgot to put AM/PM?

12:00 am
12:00 pm

12:00
24:00

00:00
0:00

2.2.2.3. Times after 24:00

23:59:59
23:59:60
24:00
24:01
25:00
27:45
14:00-30:00

2.2.2.4. Military time

1200J
1200Z

2.2.3. ISO 8601 Standard

2.2.3.1. Dates

1961-04-12

2.2.3.2. Date and time

  • "Z" (Zulu) means UTC

  • "T" separates date and time

Listing 2.50. Date and time
1961-04-12T06:07:00Z
1961-04-12T06:07:00.123Z
1961-04-12T06:07:00.123456Z

2.2.3.3. Noon and Midnight

  • "00:00" - midnight, at the beginning of a day

  • "24:00" - midnight, at the end of a day (not recommended)

  • "2007-04-05T24:00" is equal to "2007-04-06T00:00"

2.2.3.4. Weeks

Listing 2.51. Note year/month changes during the week
2009-W01            # First week of 2009
2009-W01-1          # Monday 29 December 2008
2009-W53-7          # Sunday 3 January 2010

2.2.3.5. Timezone

  • "Z" (Zulu) means UTC

Listing 2.52. Time zone notation
<time>UTC
<time>Z
<time>±hh:mm
<time>±hhmm
<time>±hh

2.2.3.6. Duration

  • Format: P[n]Y[n]M[n]DT[n]H[n]M[n]S

Table 2.1. Duration format

Format

Designator

Description

P

duration (period)

placed at the start of the duration representation

Y

year

number of years

M

month

number of months

W

week

number of weeks

D

day

number of days

T

time

precedes the time components of the representation

H

hour

number of hours

M

minute

number of minutes

S

second

number of seconds

Listing 2.53. Example
P8Y3M8DT20H49M15S

# Period of:
#   8 years
#   3 months
#   8 days
#   20 hours
#   49 minutes
#   15 seconds

2.2.4. Date and time parsing and formatting parameters

Note

Almost any programming language has very similar date formatting parameters. There are only some minor differences like in JavaScript minutes are i, not M.

Table 2.2. Date and time parsing and formatting parameters

Directive

Example

Meaning

%a

Sun, Mon, …, Sat

Weekday as locale's abbreviated name

%A

Sunday, Monday, …, Saturday (en_US)

Weekday as locale's full name

%w

0, 1, …, 6

Weekday as a decimal number, where 0 is Sunday and 6 is Saturday

%d

01, 02, …, 31

Day of the month as a zero-padded decimal number

%b

Jan, Feb, …, Dec (en_US)

Month as locale's abbreviated name

%B

January, February, …, December (en_US)

Month as locale’s full name

%m

01, 02, …, 12

Month as a zero-padded decimal number

%y

00, 01, …, 99

Year without century as a zero-padded decimal number

%Y

0001, 0002, …, 2013, 2014, …, 9998, 9999

Year with century as a decimal number

%H

00, 01, …, 23

Hour (24-hour clock) as a zero-padded decimal number

%I

01, 02, …, 12

Hour (12-hour clock) as a zero-padded decimal number

%p

AM, PM (en_US)

Locale’s equivalent of either AM or PM

%M

00, 01, …, 59

Minute as a zero-padded decimal number

%S

00, 01, …, 59

Second as a zero-padded decimal number

%f

000000, 000001, …, 999999

Microsecond as a decimal number, zero-padded on the left

%z

(empty), +0000, -0400, +1030

UTC offset in the form +HHMM or -HHMM (empty string if the object is naive)

%Z

(empty), UTC, EST, CST

Time zone name (empty string if the object is naive)

%j

001, 002, …, 366

Day of the year as a zero-padded decimal number

%U

00, 01, …, 53

Week number of the year (Sunday as the first day of the week) as a zero padded decimal number. All days in a new year preceding the first Sunday are considered to be in week 0

%W

00, 01, …, 53

Week number of the year (Monday as the first day of the week) as a decimal number. All days in a new year preceding the first Monday are considered to be in week 0

%c

Tue Aug 16 21:30:00 1988 (en_US)

Locale’s appropriate date and time representation

%x

08/16/1988 (en_US); 16.08.1988 (de_DE)

Locale’s appropriate date representation

%X

21:30:00

Locale’s appropriate time representation

%%

%

A literal % character

%G

0001, 0002, …, 2013, 2014, …, 9998, 9999

ISO 8601 year with century representing the year that contains the greater part of the ISO week (%V)

%u

1, 2, …, 7

ISO 8601 weekday as a decimal number where 1 is Monday

%V

01, 02, …, 53

ISO 8601 week as a decimal number with Monday as the first day of the week. Week 01 is the week containing Jan 4

Todo

Convert table into smaller parts, based on categories: months, day, hour etc.

2.2.5. Date formatting

2.2.5.1. ISO Format

Listing 2.54. Datetime formatting to ISO format
from datetime import datetime

dt = datetime(1969, 7, 21, 2, 56, 15)

dt.isoformat()
# 1969-07-21T02:56:15
Listing 2.55. Date formatting to ISO format
from datetime import date

d = date(1969, 7, 21)

d.isoformat()
# 1969-07-21

2.2.5.2. f-string formatting

Listing 2.56. Datetime formatting as string with f'...'
from datetime import datetime

gagarin = datetime(1961, 4, 12, 6, 7)

print(f'Gagarin launched on {gagarin:%Y-%m-%d}')
# Gagarin launched on 1961-04-12
Listing 2.57. Datetime formatting as string with f'...'
from datetime import datetime

gagarin = datetime(1961, 4, 12, 6, 7)

print(f'Gagarin launched on {gagarin:%Y-%m-%d %H:%M}')
# Gagarin launched on 1961-04-12 06:07
Listing 2.58. Datetime formatting as string with f'...'
from datetime import datetime

gagarin = datetime(1961, 4, 12, 6, 7)
format = '%Y-%m-%d %H:%M'

print(f'Gagarin launched on {gagarin:{format}}')
# Gagarin launched on 1961-04-12 06:07

2.2.5.3. Format to string

Listing 2.59. Datetime formatting as string with .strftime()
from datetime import datetime

gagarin = datetime(1961, 4, 12, 6, 7)
formatted = gagarin.strftime('%Y-%m-%d %H:%M')

print(f'Gagarin launched on {formatted}')
# Gagarin launched on 1961-04-12 06:07

2.2.6. Parsing dates

  • Parsing - analyze (a sentence) into its parts and describe their syntactic roles.

Listing 2.60. Datetime parsing from string
from datetime import datetime

sputnik = '4 October 1957, 19:28:34 [UTC]'

result = datetime.strptime(sputnik, '%d %B %Y, %H:%M:%S [%Z]')
# datetime.datetime(1957, 10, 4, 19, 28, 34)

print(result)
# 1957-10-04 19:28:34

2.2.7. Examples

from datetime import datetime


log = '1969-07-21T02:56:15.123 [WARNING] First step on the Moon'

date, level, message = log.split(maxsplit=2)
format = '%Y-%m-%dT%H:%M:%S.%f'
date = datetime.strptime(date, format)

print(date)
# 1969-07-21 02:56:15.123000

print(level)
# [WARNING]

print(message)
# First step on the Moon

2.2.8. Assignments

2.2.8.1. Datetime Parse ISO

English
  1. Use data from "Input" section (see below)

  2. The date and time is given in ISO format:

  3. Convert it to datetime object

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Dana jest data w formacie ISO

  3. Przedstaw datę jako obiekt datetime

Input
DATA = '1969-07-21T02:56:15.123Z'

2.2.8.2. Datetime Parse Local

Enlish
  1. Use data from "Input" section (see below)

  2. Create datetime object by parsing the given date

  3. Using formatting parameters print the date and time in ISO format

  4. Compare result with "Output" section (see below)

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Podaną datę przekonwertuj do obiektu datetime

  3. Używając parametrów formatujących wyświetl datę i czas w formacie ISO

  4. Porównaj wyniki z sekcją "Output" (patrz poniżej)

Input
DATA = 'April 12, 1961 6:07 local time'
Output
data: datetime
# datetime.datetime(1961, 4, 12, 6, 7)

print(result)
# 1961-04-12T06:07:00.000000Z
Hint
  • Add string local time to format statement

2.2.8.3. Datetime Parse US

English
  1. Use data from "Input" section (see below)

  2. Using given date and time from below (copy with quotes inside)

  3. Create datetime object by parsing the date

  4. Using formatting parameters print american short date format

  5. Make sure, that hour is without leading zero

  6. Compare result with "Output" section (see below)

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Używając podaną poniżej datę i czas (skopiuj z cudzysłowami)

  3. Parsując stwórz obiekt datetime

  4. Używając parametrów formatowania wyświetl datę w formacie amerykańskim krótkim

  5. Upewnij się, że godzina jest bez wiodącego zera

  6. Porównaj wyniki z sekcją "Output" (patrz poniżej)

Input
DATA = '"July 21st, 1969 2:56:15 AM UTC"'
Output
data: datetime
# datetime.datetime(1969, 7, 21, 2, 56)

print(result)
# 7/21/69 2:56 AM
Hint
  • Add quote sign " like normal text to fmt parameter of .strptime()

  • Use %-I or %_I on *nix systems (macOS, BSD, Linux) to remove leading zero

  • Use %#I on Windows to remove leading zero

2.2.8.4. Datetime Parse Logs

English
  1. Use data from "Input" section (see below)

  2. Save input data to file apollo11-timeline.log

  3. Extract datetime object, level name and message from each line

  4. Collect data to result: List[dict]

  5. Print result

  6. Compare result with "Output" section (see below)

Polish
  1. Użyj danych z sekcji "Input" (patrz poniżej)

  2. Zapisz dane wejściowe do pliku apollo11-timeline.log

  3. Wyciągnij obiekt datetime, poziom logowania oraz wiadomość z każdej linii

  4. Zbierz dane do result: List[dict]

  5. Wyświetl result

  6. Porównaj wyniki z sekcją "Output" (patrz poniżej)

Input
DATA = """
    1969-07-14, 21:00:00, INFO, Terminal countdown started
    1969-07-16, 13:31:53, WARNING, S-IC engine ignition (#5)
    1969-07-16, 13:33:23, DEBUG, Maximum dynamic pressure (735.17 lb/ft^2)
    1969-07-16, 13:34:44, WARNING, S-II ignition
    1969-07-16, 13:35:17, DEBUG, Launch escape tower jettisoned
    1969-07-16, 13:39:40, DEBUG, S-II center engine cutoff
    1969-07-16, 16:22:13, INFO, Translunar injection
    1969-07-16, 16:56:03, INFO, CSM docked with LM/S-IVB
    1969-07-16, 17:21:50, INFO, Lunar orbit insertion ignition
    1969-07-16, 21:43:36, INFO, Lunar orbit circularization ignition
    1969-07-20, 17:44:00, INFO, CSM/LM undocked
    1969-07-20, 20:05:05, WARNING, LM powered descent engine ignition
    1969-07-20, 20:10:22, ERROR, LM 1202 alarm
    1969-07-20, 20:14:18, ERROR, LM 1201 alarm
    1969-07-20, 20:17:39, WARNING, LM lunar landing
    1969-07-21, 02:39:33, DEBUG, EVA started (hatch open)
    1969-07-21, 02:56:15, WARNING, 1st step taken lunar surface (CDR)
    1969-07-21, 02:56:15, WARNING, That's one small step for [a] man... one giant leap for mankind
    1969-07-21, 03:05:58, DEBUG, Contingency sample collection started (CDR)
    1969-07-21, 03:15:16, INFO, LMP on lunar surface
    1969-07-21, 05:11:13, DEBUG, EVA ended (hatch closed)
    1969-07-21, 17:54:00, WARNING, LM lunar liftoff ignition (LM APS)
    1969-07-21, 21:35:00, INFO, CSM/LM docked
    1969-07-22, 04:55:42, WARNING, Transearth injection ignition (SPS)
    1969-07-24, 16:21:12, INFO, CM/SM separation
    1969-07-24, 16:35:05, WARNING, Entry
    1969-07-24, 16:50:35, WARNING, Splashdown (went to apex-down)
    1969-07-24, 17:29, INFO, Crew egress
"""
Output
result: List[dict] = [

     {'date': datetime.datetime(1969, 7, 14, 21, 0),
      'level': 'INFO',
      'message': 'Terminal countdown started'},

     {'date': datetime.datetime(1969, 7, 16, 13, 31, 53),
      'level': 'WARNING',
      'message': 'S-IC engine ignition (#5)'},

     {'date': datetime.datetime(1969, 7, 16, 13, 33, 23),
      'level': 'DEBUG',
      'message': 'Maximum dynamic pressure (735.17 lb/ft^2)'},

...]