Using Python datetime to Work With Dates and Times
Datetime module, extensions and more...
Each time, I try to solve a problem that I have encountered or wondered about by thinking about the programming languages that I am familiar with, such as R, Python, JS, and the different libraries these languages have. The main reason for this comparison is that I want to practice by keeping my memory sharp and being open to different solution methods. I will post a few more articles on this subject.
In this article, I will explain how we can use the datetime
module that the Python programming language offers as a built-in in this article and give some examples.
With the lubridate package, which is a part of the tidyverse collection developed for the R programming language, we can operate comprehensive date and time operations and manage data types easily1.
On the JavaScript/NodeJS side, there is the datetime module that I can remember2. On the Python side, the well-known module is offered with the name datetime by default as well. Besides, I did a little research about alternative packages that could be used, and in the last part of the article, mentioned them.
Datetime Module
Python does not have any date-time data types. However, with the datetime
module, we can use the strings as date-time.
While working on an example, I had the opportunity to examine both the datetime
module documentation and perform sample operations on the presented methods for date operations. In this article, I would like to share the short notes I took and give a few simple examples3 4.
The date operation in the relevant example was as follows:
currentTime = datetime.datetime.today().strftime('%Y-%m-%d') # '2021-07-31'
previousTime = (datetime.datetime.today() - datetime.timedelta(days=7)).strftime('%Y-%m-%d') # '2021-07-24'
We can include the datetime
module in our works with import datetime
or we only call the relevant class for specified operations such as date
, time
, and datetime
.
from datetime import datetime # datetime.now()
# import datetime # datetime.datetime.now()
# dir(datetime.datetime)
# ['__add__', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__rsub__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', 'astimezone', 'combine', 'ctime', 'date', 'day', 'dst', 'fold', 'fromisoformat', 'fromordinal', 'fromtimestamp', 'hour', 'isocalendar', 'isoformat', 'isoweekday', 'max', 'microsecond', 'min', 'minute', 'month', 'now', 'replace', 'resolution', 'second', 'strftime', 'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'today', 'toordinal', 'tzinfo', 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', 'utctimetuple', 'weekday', 'year']
While the date
class enables operations related to dates, time
contains time-related operations. datetime
includes date
and time
classes.
NOW and TODAY
The now()
and today()
methods give us the current year, month, day, hour, minute, second, and microsecond information. It is also possible to call this time information separately.
datetime.datetime.today() # datetime.datetime(2021, 7, 31, 19, 31, 46, 197762)
datetime.datetime.now().year # 2021
datetime.datetime.now().month # 7
datetime.datetime.now().day # 31
datetime.datetime.now().hour # 19
datetime.datetime.now().minute # 31
datetime.datetime.now().second # 46
datetime.datetime.now().microsecond # 197762
STRFTIME and STRPTIME
The strftime()
method allows us to manage the date and time formats via directives, and as a result of this process, the date object is converted to a character string.
datetime.datetime.now().strftime(format='%Y') # 2021
datetime.datetime.now().strftime(format='%m/%d/%y') # 07/31/21
datetime.datetime.now().strftime(format='%x') # 07/31/21
datetime.datetime.now().strftime(format='%d.%m.%Y') # 31.07.2021
The strptime()
method, on the other hand, allows us to convert a string of characters to a date object using date and time formats.
datetime.datetime.strptime('31 July 2014 12:34:44', '%d %B %Y %H:%M:%S') # datetime.datetime(2014, 7, 31, 12, 34, 44)
datetime.datetime.strptime('07/31/21', '%m/%d/%y') # datetime.datetime(2021, 7, 31, 0, 0)
datetime.datetime.strptime('07/31/21', '%x') # datetime.datetime(2021, 7, 31, 0, 0)
In another example, let's convert date-time data with different separators into date types. At this stage, I will also include the re
package, which allows us to perform regex operations, in the example.
import re
dates = [datetime.datetime.strptime(re.sub('[^0-9]', '/', d), '%m/%d/%Y') for d in ['11-23-2021', '05/06/1991', '10 10 2000']]
print(dates)
Some of The Most Used Directives
The table below shows some of the frequently used directives5 6.
Direktif | Anlamı | Örnek |
---|---|---|
%X | Locally formatted time | 21:30:00 (en_US) |
%x | Locally formatted date | 08/16/1988 (en_US) |
%Y | 4 digit year | 2021, 1990, vb. |
%y | 2 digit year | 21,90, vb. |
%m | Numerically the month | 01, 10, 12 |
%B | Locally formated month | July, Temmuz, vb. |
%b | Locally formated, shortened month | Jul, Tem, vb. |
%A | Locally formated name of the day | Monday, Pazartesi, vb. |
%a | Locally adapted, shortened name of the day | Mon, Pzt, vb. |
%w | Numerical day of the week | 0 (Sunday), 3, 6, vb. |
%d | Numerical day of the month | 01, 22, 31, vb. |
%H | 24-hour time | 00, 11, 23, vb. |
%I | 12-hour time | 01, 10, 24, vb. |
%p | Locally formated day period | AM, ÖÖ, PM, ÖS |
%M | Minute | 00,33,59 |
%S | Second | 00, 33, 59 |
%Z | Time zone | UTC, EST, GMT, vb. |
%z | Time zone in numeric format | +0000, -0400, vb. |
Local definitions may vary depending on the system. You can execute the locale -a
command on the command line to see the selectable definitions. It will return an output like this command.
C
C.UTF-8
en_US.utf8
tr_TR
POSIX
It is also possible to display local information with the Python module locale
7.
import locale
print(locale.getlocale()) # ('en_US', 'UTF-8')
We can use the setlocale()
method to select options listed with locale -a
.
locale.setlocale(locale.LC_ALL, 'en_US')
datetime.datetime.now().strftime(format='%b') # Aug
datetime.datetime.now().strftime(format='%x') # 07/31/2021
locale.setlocale(locale.LC_ALL, 'tr_TR')
datetime.datetime.now().strftime(format='%b') # Ağu
datetime.datetime.now().strftime(format='%x') # 31/07/2021
CTIME
The ctime()
method returns a legible character string of the specified date and time.
datetime.datetime.today().ctime() # Sat Jul 31 21:21:24 2021
datetime.datetime(2021, 7, 1).ctime() # Thu Jul 1 00:00:00 2021
(datetime.datetime.today() - datetime.timedelta(days=217)).ctime() # Sat Dec 26 21:24:04 2020
datetime.datetime.ctime(datetime.datetime.now()) # Sun Aug 1 07:21:55 2021
TIMESTAMP and FROMTIMESTAMP
In file/directory operations, we display values such as the creation and modified dates in timestamp format.
os.stat('Image.png').st_mtime #1627801430.7354434
The timestamp()
method allows us to convert date and time values into timestamp format.
datetime.datetime.today().timestamp() # 1627802786.984535
(datetime.datetime.today() - datetime.timedelta(days=217)).timestamp() # 1609054148.42208
datetime.datetime.fromtimestamp(datetime.datetime.timestamp(datetime.datetime.now())) # datetime.datetime(2021, 8, 1, 7, 33, 7, 576549)
The fromtimestamp()
method enables the time stamp to be converted to a human readable format.
datetime.datetime.fromtimestamp(1627802786.984535) # datetime.datetime(2021, 8, 1, 7, 26, 26, 984535)
Other Methods
Let's briefly mention other issues that we use for time operations.
ISOFORMAT and FROMISOFORMAT
The isoformat()
method allows us to get the date-time value in ISO format.
datetime.datetime.utcfromtimestamp(1627804283.441646).isoformat() # 2021-08-01T07:51:23.441646
The fromisoformat()
method converts the historical expression in ISO format into a datetime object.
datetime.fromisoformat('2021-08-01T00:05:23') # datetime.datetime(2021, 8, 1, 0, 5, 23)
TIMEDELTA
The Timedelta object represents a period, the difference between two dates or times, so comparisons and mathematical operations can be performed8.
datetime.datetime.today() - datetime.timedelta(days=7) # datetime.datetime(2021, 7, 25, 8, 2, 45, 800333)
datetime.datetime.today() + datetime.timedelta(days=-127) # datetime.datetime(2021, 3, 27, 8, 16, 3, 744547)
(datetime.datetime.today() - datetime.timedelta(days=50, hours=8, seconds=27, microseconds=10, minutes=5)).isoformat() # 2021-06-11T23:59:19.479398
REPLACE
datetime.datetime(2002, 12, 31).replace(day=15) # datetime.datetime(2002, 12, 15, 0, 0)
datetime.datetime(2021, 5, 10).replace(year=1995, month=11, day=15).isocalendar() # (1995, 46, 3)
OTHER MODULES
PANDAS
In addition to the default datetime
module, it is possible to perform operations with datetime
and timedelta
objects offered in Pandas9 10.
import pandas as pd
pd.to_datetime("1th of Aug, 2021") # Timestamp('2021-08-01 00:00:00')
df = pd.DataFrame(['2021-10-05', '2019-05-06', '2015-03-11'], columns=['Dates'])
[(pd.Timestamp(dt) + pd.Timedelta('-15 day')).day_name() for dt in df['Dates']] # ['Monday', 'Sunday', 'Tuesday']
pd.Timedelta("1 days 2 hours") # Timedelta('1 days 02:00:00')
pd.Timedelta(pd.offsets.Day(2)) # Timedelta('2 days 00:00:00')
pd.Series(pd.date_range("2012-1-1", periods=3, freq="D"))
'''
0 2012-01-01
1 2012-01-02
2 2012-01-03
dtype: datetime64[ns]
'''
pd.date_range("2018-01-01", periods=3, freq="H")
'''
DatetimeIndex(['2018-01-01 00:00:00', '2018-01-01 01:00:00', '2018-01-01 02:00:00'],
dtype='datetime64[ns]', freq='H')
'''
DATEUTIL
dateutil
can be considered a more practical and improved version of datetime
11.
from datetime import *; from dateutil.relativedelta import *
import calendar
NOW = datetime.now()
TODAY = date.today()
print(NOW) # 2021-08-01 08:43:27.891459
print(TODAY) # 2021-08-01
NOW+relativedelta(months=+1) # datetime.datetime(2021, 9, 1, 8, 45, 51, 522361)
ARROW
Arrow developed for Python is comparable to the lubridate package developed for the R programming language12. Especially its time zones methods are so handy.
import arrow
arrow.utcnow() # <Arrow [2021-08-01T08:49:17.631022+00:00]>
arrow.utcnow().shift(hours=-1) # <Arrow [2021-08-01T07:50:21.604033+00:00]>
arrow.utcnow().to('GMT+3') # <Arrow [2021-08-01T11:53:15.176165+03:00]>
arrow.utcnow().to('GMT-3').shift(hours=-1) # <Arrow [2021-08-01T10:54:03.573688+03:00]>
arrow.utcnow().to('EST').shift(hours=2).humanize() # in 2 hours
SIMPLEDATE
The Simpledate package offers several facilitating methods, especially converting between formats, such as timezone and formats13.
!pip install pytz tzlocal simple-date
import simpledate
simpledate.SimpleDate(tz='America/New_York') # SimpleDate('2021-08-01 05:19:47.150963 EDT', tz='America/New_York')
simpledate.SimpleDate(tz=120, format='%Y-%m-%d %z') # SimpleDate('2021-08-01 +0200', tz='pytz.FixedOffset(120)')
simpledate.SimpleDate('2013-01-01', tz='EST', country='US') # SimpleDate('2013-01-01')
simpledate.SimpleDate('6/12/2013', format='%m/%d/%Y') # SimpleDate('06/12/2013', tz='Etc/UTC')
[simpledate.best_guess_utc(date) for date in ['1/6/2013 BST', '1/6/2013 EST', 'Tue, 18 Jun 2013 12:19:09 -0400']]
'''
[datetime.datetime(2013, 5, 31, 23, 0, tzinfo=<UTC>),
datetime.datetime(2013, 1, 6, 5, 0, tzinfo=<UTC>),
datetime.datetime(2013, 6, 18, 16, 19, 9, tzinfo=<UTC>)]
'''
pd.date_range("2018-01-01", periods=3, freq="H")
'''
DatetimeIndex(['2018-01-01 00:00:00', '2018-01-01 01:00:00', '2018-01-01 02:00:00'],
dtype='datetime64[ns]', freq='H')
'''
pd.date_range(start='1/1/2018', end='1/08/2018')
'''
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04',
'2018-01-05', '2018-01-06', '2018-01-07', '2018-01-08'],
dtype='datetime64[ns]', freq='D')
'''
pd.date_range(start='1/1/2018', periods=5, freq='M')
'''
DatetimeIndex(['2018-01-31', '2018-02-28', '2018-03-31', '2018-04-30',
'2018-05-31'],
dtype='datetime64[ns]', freq='M')
'''
df = pd.DataFrame({'Dates': ['2021-10-05', '2021-10-06', '2021-10-04','2021-11-15', '2021-11-21', '2021-11-09'], 'Counts': [20,23,41,55,32,24]})
df['Dates'] = pd.to_datetime(df['Dates'])
df.resample('M', on='Dates')['Counts'].mean()
'''
Dates
2021-10-31 28.0
2021-11-30 37.0
Freq: M, Name: Counts, dtype: float64
'''
df['Counts'].groupby(df['Dates'].dt.month).mean()
'''
Dates
10 28.0
11 37.0
Name: Counts, dtype: float64
'''
That's all for now, my notes on the datetime
package. I will continue to add new notes and examples in the future.
- Lubridate. Make Dealing with Dates a Little Easier ↩
- node-datetime. npm ↩
- Python DateTime, TimeDelta, Strftime(Format) with Examples ↩
- Bryan Weber. Using Python datetime to Work With Dates and Times ↩
- Basic Date and Time Types - strftime() and strptime() Format Codes ↩
- Python strftime cheatsheet ↩
- locale — Internationalization services. Python 3.x Documentation ↩
- Miguel Brito. (2020). How to Use datetime.timedelta in Python With Examples ↩
- Time series / date functionality. Pandas Documentation ↩
- Time deltas. Pandas Documentation ↩
- dateutil - powerful extensions to datetime ↩
- arrow. Better dates & times for Python ↩
- andrewcooke/simple-date. GitHub ↩