# 22. Dates and Time¶

Warning

If you’re thinking about implementing your own time calculator or system, watch Computerophile Time & Time Zones https://www.youtube.com/watch?v=-5wpm-gesOY

## 22.1. Date and time formats¶

### 22.1.1. Date formats¶

• Which format is a formal standard in USA?
• Which format is a formal standard in Germany?
• Which format is a formal standard 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
4/12/61
April 12, 1961


### 22.1.2. Time formats¶

• Which time is a midnight?
• Which time is a noon?
12:00 am
12:00 pm
12:00
23:59
24:00
0:00
00:00


### 22.1.3. ISO 8601 Standard¶

• Dates:

• Date and time

1961-04-12T06:07:00

• Date and time with microseconds

1961-04-12T06:07:00.123456


## 22.2. datetime¶

### 22.2.1. Creating date and datetime objects¶

Code Listing 22.1. Creating date and datetime objects
from datetime import datetime, date

now = datetime.now()
today = date.today()

gagarin = date(1961, 4, 12)
armstrong = datetime(1969, 7, 21, 14, 56, 15)
midnight = datetime(1957, 10, 4)


### 22.2.2. Date formatting¶

Code Listing 22.2. Datetime formatting as string
from datetime import datetime

now = datetime.now()

print(f'Now is {now:%Y-%m-%d %H:%M}!')
# Now is 2017-12-19 17:40!


### 22.2.3. Parsing dates¶

• Parsing - analyze (a sentence) into its parts and describe their syntactic roles.
Code Listing 22.3. Datetime parsing from string
from datetime import datetime

sputnik = '4 October 1957 19:28:34 UTC'

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

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


### 22.2.4. Table of date and time parsing and formatting parameters¶

Note

Prawie wszystkie parametry są podobne różnych językach programowania. Od czasu do czasu występują małe zmiany, np. w JavaScript minuty to i a nie M

Tab. 22.1. Tabelka parametrów formatowania i parsowania dat i czasu
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

### 22.2.5. Time shifts and time deltas¶

Code Listing 22.4. Shifting datetimes
from datetime import datetime

gagarin = datetime(1961, 4, 12, 6, 7)
armstrong = datetime(1969, 7, 21, 14, 56, 15)

duration = armstrong - gagarin            # datetime.timedelta(3022, 31755)

duration                                  # 3022 days, 8:49:15
duration.seconds                          # 31755
duration.days                             # 3022
duration.total_seconds()                  # 261132555.0 (days * seconds per day + seconds)

Code Listing 22.5. Substract time from datetimes
from datetime import datetime, timedelta, date

# Average days a month in solar calendar
MONTH = timedelta(days=30.436875)

datetime.now() - timedelta(hours=3)
date(1961, 4, 12) - timedelta(days=3)

month_before = date(1961, 4, 12) - MONTH
# datetime.date(1961, 3, 13)

Code Listing 22.6. Diff between datetimes
from datetime import datetime

SECOND = 1
MINUTE = 60 * SECOND
HOUR = 60 * MINUTE
DAY = 24 * HOUR
MONTH = 30.436875               # Average days a month in solar calendar
YEAR = 365.2425                 # Solar calendar

gagarin = datetime(1961, 4, 12, 6, 7)
armstrong = datetime(1969, 7, 21, 14, 56, 15)
duration = armstrong - gagarin  # datetime.timedelta(3022, 31755)

years, days = divmod(duration.days, YEAR)
months, days = divmod(days, MONTH)
hours, minutes = divmod(duration.seconds, HOUR)
minutes, seconds = divmod(minutes, MINUTE)

difference = {
'years': int(years),
'months': int(months),
'days': int(days),
'hours': int(hours),
'minutes': int(minutes),
'seconds': int(seconds),
}

print(difference)
# {'years': 8, 'months': 3, 'days': 8, 'hours': 8, 'minutes': 49, 'seconds': 15}


### 22.2.6. Time zones in datetime library¶

• Always keep dates and times only in UTC (important!)
• Datetimes should be converted to localtime only when displaying to user
Code Listing 22.7. Make timezone aware object from naive datetime
from datetime import datetime, timezone

datetime.now()
datetime.utcnow()
datetime(1957, 10, 4, 19, 28, 34)

datetime.now(tz=timezone.utc)
datetime(1957, 10, 4, 19, 28, 34, tzinfo=timezone.utc)


## 22.3. pytz¶

### 22.3.1. List of Timezones¶

Code Listing 22.8. pytz brings the Olson tz database into Python.
from pytz import utc, timezone

utc = utc
eastern = timezone('US/Eastern')
warsaw = timezone('Europe/Warsaw')


### 22.3.2. From UTC to local time¶

Code Listing 22.9. From UTC to local time
from datetime import datetime
from pytz import timezone, utc

armstrong = datetime(1969, 7, 21, 14, 56, 15, tzinfo=utc)

utc_time = armstrong.astimezone(utc)
# datetime.datetime(1969, 7, 21, 14, 56, 15, tzinfo=<UTC>)

print(f'{utc_time:%Y-%m-%d %H:%M:%S %Z%z}')
# 1969-07-21 14:56:15 UTC+0000

waw_time = armstrong.astimezone(timezone('Europe/Warsaw'))
# datetime.datetime(1969, 7, 21, 15, 56, 15, tzinfo=<DstTzInfo 'Europe/Warsaw' CET+1:00:00 STD>)

print(f'{waw_time:%Y-%m-%d %H:%M:%S %Z%z}')
# 1969-07-21 15:56:15 CET+0100


### 22.3.3. From local to UTC¶

Code Listing 22.10. From local to UTC
from datetime import datetime
from pytz import utc, timezone

warsaw = timezone('Europe/Warsaw')
gagarin = datetime(1961, 4, 12, 14, 7)

in_utc = utc.localize(gagarin, is_dst=None)
# datetime.datetime(1961, 4, 12, 14, 7, tzinfo=<UTC>)

in_waw = warsaw.localize(gagarin, is_dst=None)
# datetime.datetime(1961, 4, 12, 14, 7, tzinfo=<DstTzInfo 'Europe/Warsaw' CET+1:00:00 STD>)


### 22.3.4. Between timezones¶

Code Listing 22.11. Between timezones
from datetime import datetime
from pytz import utc, timezone

gagarin = datetime(1961, 4, 12, 14, 7, tzinfo=timezone('Asia/Almaty'))
in_utc = gagarin.astimezone(utc)
in_waw = gagarin.astimezone(timezone('Europe/Warsaw'))

print(f'{in_utc:%Y-%m-%d %H:%M:%S %Z%z}')
# 1961-04-12 08:59:00 UTC+0000

print(f'{in_waw:%Y-%m-%d %H:%M:%S %Z%z}')
# 1961-04-12 09:59:00 CET+0100


## 22.4. calendar¶

Code Listing 22.12. HTML Calendar
from calendar import HTMLCalendar

html = HTMLCalendar().formatmonth(1969, 7)

print(html)
# <table border="0" cellpadding="0" cellspacing="0" class="month">
# <tr><th colspan="7" class="month">July 1969</th></tr>
# <tr><th class="mon">Mon</th><th class="tue">Tue</th><th class="wed">Wed</th><th class="thu">Thu</th><th class="fri">Fri</th><th class="sat">Sat</th><th class="sun">Sun</th></tr>
# <tr><td class="noday">&nbsp;</td><td class="tue">1</td><td class="wed">2</td><td class="thu">3</td><td class="fri">4</td><td class="sat">5</td><td class="sun">6</td></tr>
# <tr><td class="mon">7</td><td class="tue">8</td><td class="wed">9</td><td class="thu">10</td><td class="fri">11</td><td class="sat">12</td><td class="sun">13</td></tr>
# <tr><td class="mon">14</td><td class="tue">15</td><td class="wed">16</td><td class="thu">17</td><td class="fri">18</td><td class="sat">19</td><td class="sun">20</td></tr>
# <tr><td class="mon">21</td><td class="tue">22</td><td class="wed">23</td><td class="thu">24</td><td class="fri">25</td><td class="sat">26</td><td class="sun">27</td></tr>
# <tr><td class="mon">28</td><td class="tue">29</td><td class="wed">30</td><td class="thu">31</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td><td class="noday">&nbsp;</td></tr>
# </table>


## 22.5. time¶

Code Listing 22.13. Time sleep function
import time

time.sleep(2)

Code Listing 22.14. Get timestamp
import time

time.time()
# 1496737953.0712671

time.time()
# 1496737954.3189602


## 22.6. timeit¶

### 22.6.1. timeit from Python script¶

Code Listing 22.15. Timeit simple statement
from timeit import timeit

setup = 'name="Jose Jimenez"'
stmt = 'out = f"My name... {name}"'

duration = timeit(stmt, setup, number=10000)

print(duration)
# 0.0005737080000000061

Code Listing 22.16. Timeit multiple statements with setup code
from timeit import timeit

setup = """
first_name = 'José'
last_name = 'Jiménez'
"""

TEST = dict()
TEST[0] = 'name = f"{first_name} {last_name}"'
TEST[1] = 'name = "{0} {1}".format(first_name, last_name)'
TEST[2] = 'name = first_name + " " + last_name'
TEST[3] = 'name = " ".join([first_name, last_name])'

for stmt in TEST.values():
duration = timeit(stmt, setup, number=10000)
print(f'{duration:.5}\t{stmt}')

# 0.00071559    name = f"{first_name} {last_name}"
# 0.0026514     name = "{0} {1}".format(first_name, last_name)
# 0.001015      name = first_name + " " + last_name
# 0.0013494     name = " ".join([first_name, last_name])

Code Listing 22.17. Timeit with globals()
from timeit import timeit

def factorial(n: int) -> int:
if n == 0:
return 1
else:
return n * factorial(n-1)

duration = timeit(
stmt='factorial(500); factorial(400); factorial(450)',
globals=globals(),
number=10000,
)

duration = round(duration, 6)

print(f'factorial time: {duration} seconds')
# factorial time: 2.845382 seconds


### 22.6.2. timeit from terminal¶

Code Listing 22.18. Timeit
python3 -m timeit -n100000 -r100 --setup='name="Jose Jimenez"' 'out = f"My name... {name}"'
# 100000 loops, best of 100: 55.9 nsec per loop

python3 -m timeit -n100000 -r100 --setup='name="Jose Jimenez"' 'out = "My name... {name}".format(name=name)'
# 100000 loops, best of 100: 327 nsec per loop

python3 -m timeit -n100000 -r100 --setup='name="Jose Jimenez"' 'out = "My name... %s" % name'
# 100000 loops, best of 100: 124 nsec per loop

-n N, --number=N
how many times to execute ‘statement’

-r N, --repeat=N
how many times to repeat the timer (default 5)

-s S, --setup=S
statement to be executed once initially (default pass)

-p, --process
measure process time, not wallclock time, using time.process_time() instead of time.perf_counter(), which is the default

-u, --unit=U
specify a time unit for timer output; can select nsec, usec, msec, or sec

-v, --verbose
print raw timing results; repeat for more digits precision

-h, --help
print a short usage message and exit


## 22.7. Assignments¶

### 22.7.1. Date manipulation¶

1. Dane są dwie następujące daty w formacie jak poniżej:

date1 = 'April 12, 1961 2:07 local time'  # Asia/Almaty
date2 = '"07/21/69 2:56:15 AM UTC"'

2. Przedstaw daty jako obiekt datetime

3. Wyświetl daty w formacie ISO, e.g. “1961-04-12T06:07:00.123456” w UTC

4. Odejmij obie daty od siebie

5. Oblicz ile lat i miesięcy minęło między wydarzeniami

6. Od obecnej chwili (UTC) odejmij ten sam czas, który Ci wyszedł w poprzednim punkcie

7. Wyświetl samą datę (bez czasu)

8. Ile miałeś wtedy lat?

9. Przyjmij:

• rok = 365.2425 dni
• miesiac = 30.436875 dni
About: Zadanie z gwiazdką: Filename: datetime_deltas.py Lines of code to write: 15 lines Estimated time of completion: 20 min Co to za daty, które podał użytkownik? Uwzględnij strefy czasowe. Co robiłeś przez ten czas? Wpisz “local time” jako zwykły tekst do strptime Standard ISO: ‘1961-04-12’ ‘1961-04-12T06:07:00’ ‘1961-04-12T06:07:00.123456’