Learn Python Series (#21) - Handling Dates and Time Part 1
utopian-io·@scipio·
0.000 HBDLearn Python Series (#21) - Handling Dates and Time Part 1
# Learn Python Series (#21) - Handling Dates and Time - Part 1  #### Full additional iPython tutorial sample code file included here: [https://github.com/realScipio/learn-python-series/blob/master/datetime-01.ipynb](https://github.com/realScipio/learn-python-series/blob/master/datetime-01.ipynb) #### What Will I Learn? - You will learn about the existence and conceptual use cases of the built-in Python modules `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; - Regarding the `time` module, the most important methods will be discussed; - on top of that I will explain the constructs of full-9-time tuples and time_struct objects, as well as about time formatting strings directives; - we will then discuss a complete back-and-forth time object vs time string formatting / parsing example, with which you'll probably be able to do just about anything you want to regarding the handling of dates and times with respect to UNIX timestamps (epoch-related), time_struct objects and time strings; - finally we'll briefly touch upon a few convenient `calendar` module methods that provide some additional value. #### 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](https://utopian.io/utopian-io/@scipio/learn-python-series-intro) - [Learn Python Series (#2) - Handling Strings Part 1](https://utopian.io/utopian-io/@scipio/learn-python-series-2-handling-strings-part-1) - [Learn Python Series (#3) - Handling Strings Part 2](https://utopian.io/utopian-io/@scipio/learn-python-series-3-handling-strings-part-2) - [Learn Python Series (#4) - Round-Up #1](https://utopian.io/utopian-io/@scipio/learn-python-series-4-round-up-1) - [Learn Python Series (#5) - Handling Lists Part 1](https://utopian.io/utopian-io/@scipio/learn-python-series-5-handling-lists-part-1) - [Learn Python Series (#6) - Handling Lists Part 2](https://utopian.io/utopian-io/@scipio/learn-python-series-6-handling-lists-part-2) - [Learn Python Series (#7) - Handling Dictionaries](https://utopian.io/utopian-io/@scipio/learn-python-series-7-handling-dictionaries) - [Learn Python Series (#8) - Handling Tuples](https://utopian.io/utopian-io/@scipio/learn-python-series-8-handling-tuples) - [Learn Python Series (#9) - Using Import](https://utopian.io/utopian-io/@scipio/learn-python-series-9-using-import) - [Learn Python Series (#10) - Matplotlib Part 1](https://utopian.io/utopian-io/@scipio/learn-python-series-10-matplotlib-part-1) - [Learn Python Series (#11) - NumPy Part 1](https://utopian.io/utopian-io/@scipio/learn-python-series-11-numpy-part-1) - [Learn Python Series (#12) - Handling Files](https://utopian.io/utopian-io/@scipio/learn-python-series-12-handling-files) - [Learn Python Series (#13) - Mini Project - Developing a Web Crawler Part 1](https://utopian.io/utopian-io/@scipio/learn-python-series-13-mini-project-developing-a-web-crawler-part-1) - [Learn Python Series (#14) - Mini Project - Developing a Web Crawler Part 2](https://utopian.io/utopian-io/@scipio/learn-python-series-14-mini-project-developing-a-web-crawler-part-2) - [Learn Python Series (#15) - Handling JSON](https://utopian.io/utopian-io/@scipio/learn-python-series-15-handling-json) - [Learn Python Series (#16) - Mini Project - Developing a Web Crawler Part 3](https://utopian.io/utopian-io/@scipio/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](https://utopian.io/utopian-io/@scipio/learn-python-series-17-roundup-2-combining-and-analyzing-any-to-any-multi-currency-historical-data) - [Learn Python Series (#18) - PyMongo Part 1](https://utopian.io/utopian-io/@scipio/learn-python-series-18-pymongo-part-1) - [Learn Python Series (#19) - PyMongo Part 2](https://utopian.io/utopian-io/@scipio/learn-python-series-19-pymongo-part-2) - [Learn Python Series (#20) - PyMongo Part 3](https://steemit.com/utopian-io/@scipio/learn-python-series-20-pymongo-part-3) # Learn Python Series (#21) - Handling Dates and Time Part 1 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. - The `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. - The `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. - The `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! # The `time` module ### `time.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**. ```python 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: ```python 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. ```python 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. ```python 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 - 0: 4-digit year notation (e.g. 2018) - 1: Month (e.g. 2 for February) - 2: Day (e.g. 31 for the last day of December) - 3: Hour (e.g. 23 for 11 PM) - 4: Minute (e.g. 59 for the last minute of the hour) - 5: Second (can even be 60 or 61 for leap seconds!) - 6: Day of the Week (e.g. 0 for a Monday, 6 for a Sunday) - 7: Day of the Year (e.g. 1 for Jan., 1st) - 8: Daylight savings (-1, 0, 1, where `-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. ```python 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). ```python 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 name ### `time.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()`. ```python 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. ```python 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: ```python localtime = time.ctime() print(localtime) ``` Tue May 1 20:28:15 2018 ```python localtime = time.ctime(123) print(localtime) ``` Thu Jan 1 01:02:03 1970 # Let's wrap things up with a nice back-and-forth conversion example combining it all! 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: ```python # 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 # The `calendar` module Although 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. ```python 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: ```python 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. ```python calendar.monthrange(2018, 4) ``` (6, 30) ### `calendar.weekday()` The `calendar.weekday()` method simply returns the weekday number for a given date. ```python 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. ```python 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. ```python calendar.leapdays(1978,2018) ``` 10 # What did we learn, hopefully? 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! ### Thank you for your time!
👍 scipio, steemline, analyzer, cryptocorgi, zcool, helo, stoodkev, fabiyamada, itsmikechu, parejan, jasonbu, olyup, rdvn, algo.coder, julienbh, sensation, clayjohn, tensor, curtiscolwell, ruth-elise, privacybydesign, roj, zerocoolrocker, raftaar, loshcat, greenorange, drifter1, midun, thinkingmind, diogogomes, espoem, virus95, lukestokes, lemouth, planetenamek, steemstem, simplifylife, mayowadavid, enzor, robotics101, sco, adetola, rionpistorius, de-stem, anarchyhasnogods, fancybrothers, felixrodriguez, hadji, temitayo-pelumi, justtryme90, deutsch-boost, biomimi, borislavzlatanov, lafona-miner, thevenusproject, fredrikaa, abigail-dantes, the-devil, dysfunctional, foundation, himal, star-vc, ksolymosi, rachelsmantra, nitesh9, leczy, kerriknox, saunter, peppermint24, ertwro, saunter-pl, juanjdiaz89, steem-hikers, jamhuery, gra, zeeshan003, pangoli, rjbauer85, physics.benjamin, sakura1012, alexdory, kryzsec, nedspeaks, pearlumie, chloroform, ugonma, amavi, dexterdev, dber, akeelsingh, suravsingh, whileponderin, gentleshaid, blessing97, kenadis, carloserp-2000, dna-replication, curie, locikll, pacokam8, markangeltrueman, tantawi, howtostartablog, cryptokrieg, anwenbaumeister, hendrikdegrote, sethroot, ewuoso, misterakpan, clweeks, sireh, anikekirsten, mountainjewel, victorcovrig, engmi, steem.curator, pharesim, michelios, thinknzombie, massivevibration, onartbali, benleemusic, ntowl, aamin, apteacher, torico, coloringiship, bennettitalia, alinabarbu, michaelten, mytechtrail, utopian-io,