Learn Python Series (#22) - Handling Dates and Time Part 2
Learn Python Series (#22) - Handling Dates and Time Part 2
Full additional iPython tutorial sample code file included here:
https://github.com/realScipio/learn-python-series/blob/master/datetime-02.ipynb
What Will I Learn?
- You will learn about the
datetime
module and its most-used classes and their methods; - about date/time arithmetic using
timedelta
's, which is really interesting and fun for me at least! - about the methods
timetuple()
andstrftime()
&strptime()
forming a "conversion bridge" betweentime
anddatetime
instances; - and most importantly, by going over all methods and techniques discussed in Parts 1 & 2 of the
Handling Dates and Time
subseries, hopefully you're able to know the answer - for yourself - what are the differences between thetime
anddatetime
modules, and when to use which.
Requirements
- A working modern computer running macOS, Windows or Ubuntu;
- An installed Python 3(.6) distribution, such as (for example) the Anaconda Distribution;
- The ambition to learn Python programming;
Difficulty
Intermediate
Curriculum (of the Learn Python Series
):
- Learn Python Series - Intro
- Learn Python Series (#2) - Handling Strings Part 1
- Learn Python Series (#3) - Handling Strings Part 2
- Learn Python Series (#4) - Round-Up #1
- Learn Python Series (#5) - Handling Lists Part 1
- Learn Python Series (#6) - Handling Lists Part 2
- Learn Python Series (#7) - Handling Dictionaries
- Learn Python Series (#8) - Handling Tuples
- Learn Python Series (#9) - Using Import
- Learn Python Series (#10) - Matplotlib Part 1
- Learn Python Series (#11) - NumPy Part 1
- Learn Python Series (#12) - Handling Files
- Learn Python Series (#13) - Mini Project - Developing a Web Crawler Part 1
- Learn Python Series (#14) - Mini Project - Developing a Web Crawler Part 2
- Learn Python Series (#15) - Handling JSON
- Learn Python Series (#16) - Mini Project - Developing a Web Crawler Part 3
- Learn Python Series (#17) - Roundup #2 - Combining and analyzing any-to-any multi-currency historical data
- Learn Python Series (#18) - PyMongo Part 1
- Learn Python Series (#19) - PyMongo Part 2
- Learn Python Series (#20) - PyMongo Part 3
- Learn Python Series (#21) - Handling Dates and Time Part 1
Learn Python Series (#22) - Handling Dates and Time Part 2
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!
The datetime
module
As 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.
The datetime.time
class
import 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
The datetime.date
class
In 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()
method
If 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()
method
You 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()
method
There'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()
method
A 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
The datetime.datetime
class
You 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
The datetime.timedelta
class
A 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
Performing date arithmetic using timedeltas
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 & parsing
In 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.
PS: A word or two about the datetime.tzinfo
class
The 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.
What did we learn, hopefully?
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!
Hey @scipio
We're already looking forward to your next contribution!
Decentralised Rewards
Share your expertise and knowledge by rating contributions made by others on Utopian.io to help us reward the best contributions together.
Utopian Witness!
Vote for Utopian Witness! We are made of developers, system administrators, entrepreneurs, artists, content creators, thinkers. We embrace every nationality, mindset and belief.
Want to chat? Join us on Discord https://discord.me/utopian-io
Thank you @utopian-io! Bleep! Bleep!
Thank you for the contribution It has been approved.
Need help? Write a ticket on https://support.utopian.io.
Chat with us on Discord.
[utopian-moderator]
Thank you too! :-)
this is very valuable info in your posts. It makes me wish i was less busy to learn python script.
Thanks for the kind words
Hey this is great! Do you mind if I link to this tutorial from my own? I will be adding it to utopian.io soon and I'd like to include it as a refrence link at the bottom for those who don't understand the date and time manipulations my code uses. I'd like to link to a few others in this series as well such as handling strings and lists and using import. Let me know. Are you on discord?
Feel free to link to any of my
Learn Python Series
episodes!done. :)
The explanation of the differences really helped me understand them a bit better.
I was actually coding not too long ago and ran into issues trying to parse dates and times. This helped a ton.
Good! :-)
Toda I learned about the methods timetuple() and strftime() & strptime()forming a "conversion bridge" between time and datetime instances. Thanks to you for the valuable post.
Did you seriously copy-paste that line from my tutorial, just to post this comment???
I really love your post.
My post loves you too!
Dear @scipio,
Thank you so much for posting so beautiful.
SIR was very good for your posting. Because you get many benefits with the right information, so thank you very much for posting so beautiful and helping others by providing such information in the future.