https://github.com/realScipio/learn-python-series/blob/master/datetime-01.ipynb
time, calendar and datetime, and about an external package called maya that also conveniently handles dates and times. The first two mentioned modules are in-depth discussed in this tutorial episode;time module, the most important methods will be discussed;calendar module methods that provide some additional value.Intermediate
Learn Python Series):I think it's about time ;-) to discuss with you some fundamentals regarding the handling of different date & time formats and functionality. There are a lot of programming situations in which dates and times play an important role; in some of the previous Learn Python Series episodes, where we discussed the historical currency daily openings for example, dates were involved. We only created a (JSON-based) list from old to new from it, and plotted the daily price values, but what if we wanted to know "what was the price 34 days before March 18 2018?" For situations like that, some knowledge regarding how to handle dates and times is needed.
Python does not include default / native data types for dates and times (as it does for a string and a list for example), but we can make use of the functionality provided in the time, datetime and calendar modules.
datetime module includes functionality for handling dates, times, and combinations, and you can perform some arithmetic and comparison with it. It can also do some basic conversion between datetime objects and formatted strings.time module focuses on time-related functions, but handles dates as well to a certain extent, and it includes some formatting functionality for switching between time_structs / 9-tuples and strings.calendar module can be used to format representations of days, weeks, months and years, and you can for example compute the day of the week on any date.And then there's also for example the excellent external Maya package available to work with...
Lots to learn! So let's begin!
time moduletime.time()Probably the most used time method is time.time(): it returns the number of seconds passed between "now" (the exact moment you're calling time.time()) and the epoch, being Thursday, January 1st, 1970, 00:00:00 UTC, on UNIX-like systems.
import time
localtime = time.time()
print(type(localtime), localtime)
<class 'float'> 1525031396.1437771
Nota bene: oftentimes, when calling time.time() you don't want the decimal digits but rounded seconds since the epoch. In order to do so, just convert the default float time.time() returns to an integer, like so:
localtime = int(time.time())
print(type(localtime), localtime)
<class 'int'> 1525031430
time.sleep()This pauses (suspends) the thread running for the number of seconds passed to it as its argument.
start = time.time()
time.sleep(5)
end = time.time()
print(end-start)
5.0028228759765625
PS: the time passed in between start and end is oftentimes called the "wall time".
time.localtime()In case you're interested in returning a time-tuple or a time.struct_time object returned, which both are like a wrapper holding the information about some point in time, use time.localtime() and pass in the amount of ticks (seconds) passed since the epoch, or don't use an argument to get the current time.
some_other_time = time.localtime(123)
print(some_other_time)
current_time = time.localtime()
print(current_time)
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=1, tm_min=2, tm_sec=3, tm_wday=3, tm_yday=1, tm_isdst=0)
time.struct_time(tm_year=2018, tm_mon=5, tm_mday=1, tm_hour=19, tm_min=11, tm_sec=47, tm_wday=1, tm_yday=121, tm_isdst=1)
If you're wondering how to use such a time.struct_time object: you're able to format it to your liking into a string via time.strftime() (see below).
time.mktime()The time.mktime() is the inverse of what time.localtime() does. As an argument, just pass in the time.struct_time object (or full 9-tuple).
time.mktime() will then return a floating point number, indicating the seconds since the epoch (as is the case with time.time()).
Full 9-time-tuple:
Index number: Meaning
-1 means the system library decides)Struct_time:
Works exactly the same! :-)
PS: when passing in a 9-tuple as the argument to time.mktime() to get the epoch equivalent, you don't need to worry about which day of the week or which day of the year that specific date is, you can pass in 0 for indexes 6 and 7 without a problem. However, for the last (8th) index, just pass in -1 to let the system decide whether or not to compensate for daylight savings.
some_moment = (2018, 5, 1, 21, 20, 0, 0, 0, -1)
epoch = time.mktime(some_moment)
print(epoch)
some_moment_string = time.ctime(epoch)
print(some_moment_string)
1525202400.0
Tue May 1 21:20:00 2018
time.strftime()time.strftime() returns a string, you can format precisely using a format string with directives and helper string components (if you want to), and by passing in a time-tuple (a time.struct_time object) as a second argument (being either the current time / no argument, or any time in the past or future).
localtime = time.localtime()
# Two examples regarding time string formatting
print(time.strftime('Today (%Y-%m-%d) it\'s a %A', localtime))
print(time.strftime('Right now: %A, %d %b %Y (%H:%M:%S)', localtime))
Today (2018-05-01) it's a Tuesday
Right now: Tuesday, 01 May 2018 (20:25:04)
PS:
The following (common) directives, and their meaning, are used a lot with time string formatting:
%a: abbreviated weekday name%A: full weekday name%b: abbreviated month name%B: full month name%c: date/time representation of the current locale (e.g. Sun Apr 29 22:15:37 2018)%d: day of the month (01 .. 31)%H: 24-hour clock hour (00 ..23)%j: day of the year (001 .. 366)%m: month (01 ..12)%M: minute (00 ..59)%S: seconds%w: weekday (0 .. 6)%W: week number (00 .. 53)%Y: 4-digit year%Z: Timezone nametime.strptime()Works the other way around as time.strftime() does: time.strptime() parses a time-string (as first argument) which represents a certain date/time, and a format string following a specific format as a parser helper. It returns a time.struct_time object, and works with the same directives as mentioned right above regarding time.strftime().
localtime = time.strptime("14 Feb 2015", "%d %b %Y")
print(localtime)
time.struct_time(tm_year=2015, tm_mon=2, tm_mday=14, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=45, tm_isdst=-1)
time.asctime()Returns a (current locale-based) date/time string representation of the time-tuple (or blank) passed to it as its argument.
localtime = time.asctime()
print(localtime)
Tue May 1 20:28:04 2018
time.ctime()About the same as time.asctime() but possible to pass in nothing as an argument ("now"), or seconds since the UNIX epoch:
localtime = time.ctime()
print(localtime)
Tue May 1 20:28:15 2018
localtime = time.ctime(123)
print(localtime)
Thu Jan 1 01:02:03 1970
Say, you are working with some date/time string in a specific format. And you just want to use the time module, add some time to it, and present the new time string in the same format.
Then this is how to go about that:
# Some moment in time
x_date_string = "14 Feb 2015 09:15:00"
x_time_struct = time.strptime(x_date_string, "%d %b %Y %H:%M:%S")
x_epoch = time.mktime(x_time_struct)
# 15 minutes later
y_epoch = x_epoch + 900
y_time_struct = time.localtime(y_epoch)
y_date_string = time.strftime("%d %b %Y %H:%M:%S", y_time_struct)
print(x_date_string)
print(y_date_string)
14 Feb 2015 09:15:00
14 Feb 2015 09:30:00
calendar moduleAlthough I don't use the calendar module too much, personally, I still wanted to (briefly) discuss some basic features it provides. I deliberately picked a few methods that add some additional value on top of what we've discussed above regarding functionality of the time module.
calendar.calendar()With this method, you're able to conveniently print an entire year's calendar.
import calendar
my_cal = calendar.calendar(2018)
print(my_cal)
2018
January February March
Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th
1 2 3 4 1 1
5 6 7 8 9 10 11 2 3 4 5 6 7 8 2 3 4 5 6 7 8
12 13 14 15 16 17 18 9 10 11 12 13 14 15 9 10 11 12 13 14 15
19 20 21 22 23 24 25 16 17 18 19 20 21 22 16 17 18 19 20 21 22
26 27 28 29 30 31 23 24 25 26 27 28 23 24 25 26 27 28 29
30 31
April May June
Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th
1 2 3 4 5 1 2 3 1 2 3 4 5 6 7
6 7 8 9 10 11 12 4 5 6 7 8 9 10 8 9 10 11 12 13 14
13 14 15 16 17 18 19 11 12 13 14 15 16 17 15 16 17 18 19 20 21
20 21 22 23 24 25 26 18 19 20 21 22 23 24 22 23 24 25 26 27 28
27 28 29 30 25 26 27 28 29 30 31 29 30
July August September
Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th
1 2 3 4 5 1 2 1 2 3 4 5 6
6 7 8 9 10 11 12 3 4 5 6 7 8 9 7 8 9 10 11 12 13
13 14 15 16 17 18 19 10 11 12 13 14 15 16 14 15 16 17 18 19 20
20 21 22 23 24 25 26 17 18 19 20 21 22 23 21 22 23 24 25 26 27
27 28 29 30 31 24 25 26 27 28 29 30 28 29 30
31
October November December
Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th
1 2 3 4 1 1 2 3 4 5 6
5 6 7 8 9 10 11 2 3 4 5 6 7 8 7 8 9 10 11 12 13
12 13 14 15 16 17 18 9 10 11 12 13 14 15 14 15 16 17 18 19 20
19 20 21 22 23 24 25 16 17 18 19 20 21 22 21 22 23 24 25 26 27
26 27 28 29 30 31 23 24 25 26 27 28 29 28 29 30 31
30
calendar.month()With calendar.month() you can pass in both a year and month number as arguments, and print just that single month calender, like so:
import calendar
apr_2018 = calendar.month(2018, 4)
print(apr_2018)
April 2018
Mo Tu We Th Fr Sa Su
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
calendar.monthrange()The calendar.monthrange() method returns a tuple of two integers, where the first represents the "weekday code" for the first day of that month (monday: 0, sunday: 6), and the second returns the amount of days in that month. This can be convenient to serve as input for other functions in your code.
calendar.monthrange(2018, 4)
(6, 30)
calendar.weekday()The calendar.weekday() method simply returns the weekday number for a given date.
calendar.weekday(2018,4,28)
5
calendar.isleap()The calendar.isleap() method returns True or False whether the year as its argument is a leap year or not.
calendar.isleap(2018)
False
calendar.leapdays()And as a final method (for this tutorial episode) the calendar.leapdays() method returns the number of leapdays occurring within in interval of two years.
calendar.leapdays(1978,2018)
10
In this episode, we first discussed the existance of several date/time modules within Python (time, datetime, and calendar) and we then focused on the time module specifically, going over the various built-in methods in the time module and about how to use them, providing small code examples for each method discussed.
We also discussed and listed time string formatting directives, and the index numbers and meanings of full-9-time tuples and time_struct objects, which are all needed of course to convert between time objects and strings, while in the mean time being able to do some calculations with them (using seconds as the default unit because of the UNIX timestamps nature, which are seconds as well). We then wrapped things up, considering the time module with a real-life back-and-forth conversion example; tinkering around with the format strings will probably give you all the tools you need to work with, and so some time-offsetting coding on, any kind of date/time format string.
In the next Learn Python Series episodes, we'll continue with the datetime module, and the external Maya package!