Creating and Parsing Datetime in Python with Delorean

Creating and Parsing Datetime in Python with Delorean

Introduction

Working with datetime can be a bit daunting and challenging, and handling datetime in Python is no exception. Python's built-in datetime module introduced us to several classes - date, datetime, time, timezone and timedelta, and several external libraries have spawned to address the issues present in the official module, such as Arrow.

In this guide, we'll take a look at how to create and parse datetime objects in Delorean - a library built upon pytz which is the standard library for solving problems relating to timezones, and dateutil which is used to calculate deltas between any 2 given datetime objects.

Installing Delorean Setting Up a Virtual Environment

Delorean is available for installation via pip. It is generally advisable to work in a virtual environment because it enables you to organize dependencies required by different projects isolated.

On Linux,or MacOS to create a virtual environment, we'd run:

$ python3 -m venv env
$ source env/bin/activate
$ python3 -m pip install delorean

Alternatively, on Windows we can run:

$ virtualenv env
$ .\env\Scripts\activate
$ python3 -m pip install delorean

Creating a Delorean Datetime Object

The main class we'll be working with, which represents all datetime objects is the Delorean() class. Let's go ahead and import it from the delorean module, and instantiate a datetime object:

from delorean import Delorean

dt_tm = Delorean() 
print("Datetime: ", dt_tm)

After running the code, you should see the following on your terminal/command line:

Datetime:  Delorean(datetime=datetime.datetime(2021, 7, 11, 18, 40, 43, 760187), timezone='UTC')

As usual, it's a wrapper for the standard datetime object, which is situated inside the Delorean object assigned to it. The default timezone is 'UTC', though, you can easily switch this by either defining the timezone while instantiating the object or by shifting the time to a different timezone.

Since the output is a bit hard to parse by humans - it makes sense to extract some of the data from the wrapper to make it easier to interpret. While the descending hierarchy of time is clear - it takes too long to go through it and parse it with our eyes. Let's get the date of this object and print just that:

from delorean import Delorean 
dt_tm = Delorean()

dt = Delorean().date
print("Date: ", dt)

This results in:

Date:  2021-07-11

If you're interested in just the time, without much regard for the date itself, you can get both the timezone-aware time, as well as the timezone-naive time fairly easily:

from delorean import Delorean
dt_tm = Delorean()

tm = dt_tm.datetime.time()
print("Timezone-aware time: ", tm)

naive_dt_tm = dt_tm.naive
print("Timezone-naive datetime: ", naive_dt_tm)

This results in:

Timezone-aware time:  18:40:21.235708
Timezone-naive datetime:  2021-07-11 18:40:21.235708

To change the timezone, we either supply it to the constructor call, or shift the time:

from delorean import Delorean

dt_tm = Delorean(timezone='Europe/Paris')
print("Datetime Object: ", dt_tm)
print("Time: ", dt_tm.datetime.time())
dt_tm.shift('US/Pacific')
print("Shifted time: ", dt_tm.datetime.time())
Datetime Object:  Delorean(datetime=datetime.datetime(2021, 7, 11, 20, 43, 26, 990117), timezone='Europe/Paris')
Time:  20:43:26.990117
Shifted time:  11:43:26.990117

To take a look at all the available timezones, since Delorean uses pytz under the hood - we can simply print them out:

import pytz

timezones = pytz.all_timezones
num = len(timezones)
print(f"There are {num} timezones: \n")

for tz in pytz.all_timezones:
    print(tz)

Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

Which results in:

There are 593 timezones: 

Africa/Abidjan
Africa/Accra
...
US/Michigan
US/Mountain
UTC
Universal
W-SU
WET
Zulu

Convert String to Delorean Datetime Object

No library would be complete without the ability to parse strings into datetime objects. Delorean is versatile with the string formats and assumes that the day comes first if there is any ambiguity in the parsed string. The parse() method is used to parse a string, and it optionally accepts timezone information - otherwise, 'UTC' is assumed:

import delorean

# Datetime strings of differing formats
datetime_strings = ["Mon May 12 2021 00:01:02", 
                    "25-12-2021", "8/6/2019", 
                    "15-12-1987 7:00:32", 
                    "June 5th, 2021", 
                    "5th of April, 2012", 
                    "Thu 13 of July"]

for date in datetime_strings:
    delorean_object = delorean.parse(date)
    print(delorean_object)

Running this code results in:

Delorean(datetime=datetime.datetime(2021, 5, 12, 0, 1, 2), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 12, 25, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(2019, 6, 8, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(1987, 12, 15, 7, 0, 32), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 6, 5, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(2012, 4, 5, 0, 0), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 13, 0, 0), timezone='UTC')

You can notice how in the ambiguous case of 8/6/2019, it was assumed that the day comes first, hence it was parsed as the 8th of June, instead of the 6th of August. Also, since we didn't provide the year of the final date - it's automatically assigned to the current year.

If you'd like to turn this behavior around, you can set the dayfirst argument to False. Additionally, you can also set the yearfirst argument to True, which is False by default, in which case, the first expected value will be the year:

delorean_object = delorean.parse("8/6/2019", dayfirst=False)
print(delorean_object)

This results in:

Delorean(datetime=datetime.datetime(2019, 8, 6, 0, 0), timezone='UTC')

Epoch Timestamp to Delorean Object

Since all modern computers adopted the use of UNIX time, also known as Epoch time - it's needless to say that we can convert a UNIX/Epoch timestamp into a Delorean object. This is the underlying mechanism that allows for working with time anyway. To convert a Unix timestamp into a Delorean datetime object, we use the epoch() method of the delorean module:

import delorean

timestamp = 3141592653
delorean_object = delorean.epoch(timestamp)
print(delorean_object)

We've inconspicuously used the first 10 digits of Pi to form a timestamp into the future, resulting in a time well beyond that of this guide:

Delorean(datetime=datetime.datetime(2069, 7, 21, 0, 37, 33), timezone='UTC')

Generating a Sequence of Dates

A great way to produce a sequence of Delorean objects is via the stops() generator. You can generate N dates following a pattern, such as every Tuesday, or every hour or every 10 weeks. This is useful for creating, say, monthly payment plans or calculating ROI plans for instance.

Using this approach, you can also generate a series of dates on which something should occur, such as running a script every week at the same time, to gather data from an application for aggregation. Though, you can also use the python-crontab library for that, or the underyling crontab utility tool instead.

The stops() generator accepts a freq argument, denoting the frequency, a timezone and a count, denoting how many dates it should generate. The frequency can be set to any valid Delorean constant - SECONDLY, MINUTELY, HOURLY, DAILY, WEEKLY, MONTHLY or YEARLY:

import delorean

for stop in delorean.stops(freq=delorean.HOURLY, timezone='UTC', count=10):
    print(stop)

This generates a sequence of datetime objects following this pattern:

Delorean(datetime=datetime.datetime(2021, 7, 12, 13, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 14, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 15, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 16, 35, 12), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 7, 12, 17, 35, 12), timezone='UTC')

If you're unsure how many datetime objects you want exactly but do have a target datetime in mind, you can also set it to loop until a given date occurs:

import  delorean

dt1 = delorean.Delorean().naive
dt2 = delorean.Delorean(datetime=datetime.datetime(2022, 1, 1), timezone='UTC').naive

for stop in delorean.stops(freq=delorean.MONTHLY, start=dt1, stop=dt2):
    print(stop)

Note: The stops() method only accepts timezone-naive datetime instances for the start and stop arguments, and returns timezone-aware dates. But it also requires you to specify a timezone when instantiating a Delorean instance using the constructor. What we're left with is - defining a timezone for the instance, and then using the naive datetime for both instead.

Running this code will give us a date for each month until it reaches the first of January, 2022:

Delorean(datetime=datetime.datetime(2021, 7, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 8, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 9, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 10, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 11, 12, 13, 46, 1), timezone='UTC')
Delorean(datetime=datetime.datetime(2021, 12, 12, 13, 46, 1), timezone='UTC')

Conclusion

In this guide, we've taken a look at how to create and parse Delorean objects in Python. We've seen how to convert a string to datetime in various formats, how to convert an epoch timestamp into datetime, and how to generate a sequence of dates using the stops() generator.

Last Updated: July 12th, 2021
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

Geoffery, JosephAuthor

I am a software developer with interests in open source, android development (with kotlin), backend web development (with python), and data science (with python as well).

Want a remote job?

    Prepping for an interview?

    • Improve your skills by solving one coding problem every day
    • Get the solutions the next morning via email
    • Practice on actual problems asked by top companies, like:
     
     
     

    Better understand your data with visualizations

    With over 330+ pages, you'll learn the ins and outs of visualizing data in Python with popular libraries like Matplotlib, Seaborn, Bokeh, and more.

    © 2013-2021 Stack Abuse. All rights reserved.