Full additional iPython tutorial sample code file included here:
https://github.com/realScipio/learn-python-series/blob/master/datetime-02.ipynb
datetime module and its most-used classes and their methods;timedelta's, which is really interesting and fun for me at least!timetuple() and strftime() & strptime()forming a "conversion bridge" between time and datetime instances;Handling Dates and Time subseries, hopefully you're able to know the answer - for yourself - what are the differences between the time and datetime modules, and when to use which.Intermediate
Learn Python Series):In the previous tutorial of the Learn Python Series regarding the handling of dates and time (part 1) we already learned that both the time module as well as the datetime module provide functionality for handling dates and times. The time module has some more focus on support for UNIX timestamps, and in this episode (part 2) we're going to discuss in which specific areas the datetime modules shines.
Let's begin!
datetime moduleAs compared to the time module, the datetime module - instead of mostly working with 9-tuples / time_structs and timestamps / epoch integers (ticks) - has a more modular / object-oriented type of interfacing. I will talk about the following classes, which are included in the datetime module:
datetime.time: representing time, independent of its date;datetime.date: representing dates only, independent of time;datetime.datetime: for a combination of date & time on some date;datetime.timedelta: for dealing with differences of 2 date objects or 2 time objects.datetime.time classimport datetime
t1 = datetime.time(20, 1, 59, 123456)
print(t1)
20:01:59.123456
The variable t1 is now a datetime.time instance, which has attributes. These are:
hour = t1.hour
minute = t1.minute
second = t1.second
microsecond = t1.microsecond
timezone_info = t1.tzinfo
print('Hour: ', hour)
print('Minute: ', minute)
print('Second: ', second)
print('Microsecond: ', microsecond)
print('Timezone info: ', timezone_info)
Hour: 20
Minute: 1
Second: 59
Microsecond: 123456
Timezone info: None
datetime.date classIn order to create a date instance, just pass in 3 values (year, month, day) as the arguments for datetime.date().
d1 = datetime.date(2012, 12, 31)
print(d1)
2012-12-31
Variable d1 is now a datetime.date instance, which has (defaault) attributes as well, being:
year = d1.year
month = d1.month
day = d1.day
print('Year: ', year)
print('Month: ', month)
print('Day: ', day)
Year: 2012
Month: 12
Day: 31
datetime.date.today() methodIf you want to create a current day date instance, use the datetime.date.today() class method:
today = datetime.date.today()
print(today)
2018-05-02
datetime.date.timetuple() methodYou can still use 9-tuples / timestructs on datetime.date instances by calling the datetime.date.timetuple() method. The exact same 9-tuple / time_struct attributes, as I've explained in Handling Dates and Time Part 1 regarding the time module are available for the datetime module as well via the datetime.date.timetuple() method, like so:
today_tt = today.timetuple()
year = today_tt.tm_year
month = today_tt.tm_mon
month_day = today_tt.tm_mday
hour = today_tt.tm_hour
minute = today_tt.tm_min
second = today_tt.tm_sec
week_day = today_tt.tm_wday
year_day = today_tt.tm_yday
daylight_savings = today_tt.tm_isdst
print('Year: ', year)
print('Month: ', month)
print('Day of Month: ', month_day)
print('Hour: ', hour)
print('Minute: ', minute)
print('Second: ', second)
print('Day of Week: ', week_day)
print('Day of Year: ', year_day)
print('Daylight savings: ', daylight_savings)
Year: 2018
Month: 5
Day of Month: 2
Hour: 0
Minute: 0
Second: 0
Day of Week: 2
Day of Year: 122
Daylight savings: -1
datetime.date.ctime() methodThere's also a ctime() method, like in the time module, returning a date/time string representation. But because the datetime.date class doesn't deal with time, the time components returned are that of midnight:
today_ctime = today.ctime()
print(today_ctime)
Wed May 2 00:00:00 2018
datetime.date.replace() methodA convenient way to create new date instances by using an existing date instance as a starting point, is the replace() method:
today = datetime.date.today()
print('Today: ', today.ctime())
a_month_from_today = today.replace(month=6)
print('A month from today: ', a_month_from_today.ctime())
a_year_from_today = today.replace(year=2019)
print('A year from today: ', a_year_from_today.ctime())
Today: Wed May 2 00:00:00 2018
A month from today: Sat Jun 2 00:00:00 2018
A year from today: Thu May 2 00:00:00 2019
datetime.datetime classYou probably guessed it: the datetime.datetime class is best used when you're dealing with date/time values in which relevant values for both date and time are present.
datetime.datetime.now() / datetime.datetime.today()Works the same as the datetime.date.today() method, but now includes a time component as well:
now = datetime.datetime.today()
print(now)
2018-05-02 21:40:46.430434
datetime.datetime.combine()Another pretty handy method is combine(): it creates a datetime instance by combining one date instance plus 1 time instance, like so:
some_date = datetime.date(2015, 9, 14)
some_time = datetime.time(14, 53, 0)
combined_datetime = datetime.datetime.combine(some_date, some_time)
print('some_date: ', some_date)
print('some_time: ', some_time)
print('combined_datetime: ', combined_datetime)
some_date: 2015-09-14
some_time: 14:53:00
combined_datetime: 2015-09-14 14:53:00
datetime.timedelta classA really nice class - at least I think it's cool! - is the datetime.timedelta class. It's possible to execute basic arithmetic on date / datetime instances, for example calculate how many dats are in between two dates, by subtracting them:
today = datetime.date.today()
some_day = datetime.date(2012, 10, 10)
diff_days = today - some_day
print(diff_days)
2030 days, 0:00:00
By subtracting two dates, you (implicitly) create a timedelta instance.
print(type(diff_days))
<class 'datetime.timedelta'>
And you can use a timedelta to do arithmetic to produce another date!
You can create timedeltas, in multiple time units, yourself, like so:
one_week = datetime.timedelta(weeks=1)
one_day = datetime.timedelta(days=1)
one_hour = datetime.timedelta(hours=1)
one_minute = datetime.timedelta(minutes=1)
one_second = datetime.timedelta(seconds=1)
one_millisecond = datetime.timedelta(milliseconds=1)
one_microsecond = datetime.timedelta(microseconds=1)
print('one_week: ', one_week)
print('one_day: ', one_day)
print('one_hour: ', one_hour)
print('one_minute: ', one_minute)
print('one_second: ', one_second)
print('one_millisecond: ', one_millisecond)
print('one_microsecond: ', one_microsecond)
one_week: 7 days, 0:00:00
one_day: 1 day, 0:00:00
one_hour: 1:00:00
one_minute: 0:01:00
one_second: 0:00:01
one_millisecond: 0:00:00.001000
one_microsecond: 0:00:00.000001
Now the fun part begins, by combining date / time / datetime instances with timedeltas and regular math operators!
today = datetime.date.today()
print('Today: ', today)
one_week = datetime.timedelta(weeks=1)
last_week = today - one_week
print('Last week: ', last_week)
next_week = today + one_week
print('Next week: ', next_week)
print('Days in between next and last week: ', next_week - last_week)
Today: 2018-05-02
Last week: 2018-04-25
Next week: 2018-05-09
Days in between next and last week: 14 days, 0:00:00
Because timedelta objects can work with floats, integers, and other timedelta objects, you can create interesting combinations.
How about this for getting creative with timedelta arithmetic?
vp_recharge_period = datetime.timedelta(days=1) * 0.1
powerdown_period = datetime.timedelta(weeks=13)
num_votes_during_powerdown = powerdown_period / vp_recharge_period
print('vp_recharge_period: ', vp_recharge_period)
print('powerdown_period: ', powerdown_period)
print('num_votes_during_powerdown: ', num_votes_during_powerdown)
vp_recharge_period: 2:24:00
powerdown_period: 91 days, 0:00:00
num_votes_during_powerdown: 910.0
datetime object string formatting & parsingIn the previous tutorial, regarding the time module, we've in-depth covered the usage of time.strftime() (for string formatting) and time.strptime() (for date/time string parsing). The same type of methods are also available on the datetime class.
For those that haven't read the previous tutorial regarding time.strftime() and time.strptime(), I'll briefly demonstrate how to use the same methods in a date.strftime() and date.strptime() context.
We define a date/time format string, create a datetime object (now) and convert between the two, proving the same now is used for variables s (string) and p (parsed).
format_string = "%A, %d %b %Y (%H:%M:%S)"
now = datetime.datetime.today()
s = now.strftime(format_string)
p = datetime.datetime.strptime(s, format_string)
print('strftime:', s)
print('strptime:', p)
strftime: Wednesday, 02 May 2018 (23:32:58)
strptime: 2018-05-02 23:32:58
Nota bene: Since we've also covered the datetime.date.timetuple() method, I'm sure you'll be able to conveniently make use of the most handy methods available on both the time and datetime classes, while at the same time being able to convert between the two.
datetime.tzinfo classThe datetime module is able to work with time zones as well, but as subclasses of the datetime.tzinfo class, which is abstract, and therefore you need to provide your own implementations to make the methods work. It can be ... "tricky", to say the least. You could also say that working with timezones via the datetime module is oftentimes considered "a nightmare" by many Pythonistas.
But no worries! The next Learn Python Series episode is about the external date/time package Maya, which makes your life a whole lot easier, including handling timezones.
In this episode, we went over the "ins-and-outs" of the datetime module and its classes and methods. Some of the methods are pretty straightforward (such as combine() and replace()) yet powerful to use. The most "fun" part - at least I think so - about the datetime module, is the datetime.timedelta class. Because it allows you to do date/time arithmetic using floats, integers and other timedeltas, you can get pretty creative with it in just a few lines of code!
Nota bene: One of the core take-aways I wanted to address here, by first going over in-depth regarding the time module, and then doing the same for the datetime module, is that although they overlap to a certain extent - which became clear, hopefully, by me discussing al those methods - is that both modules have their specific strengths. And, because of the timetuple() method and the strftime() & strptime() methods, forming a "conversion bridge" between the time module and the datetime module, you can freely choose to combine whatever you want!