{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Times and Dates in Python" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Overview\n", "\n", "Time is an essential component of nearly all geoscience data. Timescales commonly used in science can have many different orders of magnitude, from mere microseconds to millions or even billions of years. Some of these magnitudes are listed below:\n", "\n", "- microseconds for lightning\n", "- hours for a supercell thunderstorm\n", "- days for a global weather model\n", "- millennia and beyond for the earth's climate\n", "\n", "To properly analyze geoscience data, you must have a firm understanding of how to handle time in Python. \n", "\n", "In this notebook, we will:\n", "\n", "1. Introduce the [time](https://docs.python.org/3/library/time.html) and [datetime](https://docs.python.org/3/library/datetime.html) modules from the Python Standard Library\n", "1. Look at formatted input and output of dates and times\n", "1. See how we can do simple arithmetic on date and time data, by making use of the `timedelta` object\n", "1. Briefly make use of the [pytz](https://pypi.org/project/pytz/) module to handle some thorny time zone issues in Python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prerequisites\n", "\n", "| Concepts | Importance | Notes |\n", "| --- | --- | --- |\n", "| [Python Quickstart](../../foundations/quickstart) | Necessary | Understanding strings |\n", "| Basic Python string formatting | Helpful | Try this [Real Python string formatting tutorial](https://realpython.com/python-string-formatting/) |\n", "\n", "- **Time to learn**: 30 minutes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Imports\n", "\n", "For the examples on this page, we import three modules from the Python Standard Library, as well as one third-party module. The import syntax used here, as well as a discussion on this syntax and an overview of these modules, can be found in the next section." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Python Standard Library packages\n", "# We'll discuss below WHY we alias the packages this way\n", "import datetime as dt\n", "import math\n", "import time as tm\n", "\n", "# Third-party package for time zone handling, we'll discuss below!\n", "import pytz" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## `Time` Versus `Datetime` modules \n", "\n", "### Some core terminology\n", "\n", "Every Python installation comes with a Standard Library, which includes many helpful modules; in these examples, we cover the [time](https://docs.python.org/3/library/time.html) and [datetime](https://docs.python.org/3/library/datetime.html) modules. Unfortunately, the use of dates and times in Python can be disorienting. There are many different terms used in Python relating to dates and times, and many such terms apply to multiple scopes, such as modules, classes, and functions. For example:\n", "\n", "- `datetime` **module** has a `datetime` **class**\n", "- `datetime` **module** has a `time` **class**\n", "- `datetime` **module** has a `date` **class**\n", "- `time` **module** has a `time` function, which returns (almost always) [Unix time](#What-is-Unix-Time?)\n", "- `datetime` **class** has a `date` method, which returns a `date` object\n", "- `datetime` **class** has a `time` method, which returns a `time` object\n", "\n", "This confusion can be partially alleviated by aliasing our imported modules, we did above:\n", "\n", "```\n", "import datetime as dt\n", "import time as tm\n", "```\n", "\n", "We can now reference the `datetime` module (aliased to `dt`) and `datetime` class unambiguously." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pisecond = dt.datetime(2021, 3, 14, 15, 9, 26)\n", "print(pisecond)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Our variable `pisecond` now stores a particular date and time, which just happens to be $\\pi$-day 2021 down to the nearest second (3.1415926...)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "now = tm.time()\n", "print(now)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The variable `now` holds the current time in seconds since January 1, 1970 00:00 UTC. For more information on this important, but seemingly esoteric time format, see the section on this page called \"[What is Unix Time](#What-is-Unix-Time?)\". In addition, if you are not familiar with UTC, there is a section on this page called \"[What is UTC](#What-is-UTC?)\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `time` module\n", "\n", "The `time` module is well-suited for measuring [Unix time](#What-is-Unix-Time?). For example, when you are calculating how long it takes a Python function to run, you can employ the `time()` function, which can be found in the `time` module, to obtain Unix time before and after the function completes. You can then take the difference of those two times to determine how long the function was running. (Measuring the runtime of a block of code this way is known as \"benchmarking\".)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "start = tm.time()\n", "tm.sleep(1) # The sleep function will stop the program for n seconds\n", "end = tm.time()\n", "diff = end - start\n", "print(f\"The benchmark took {diff} seconds\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
Info
\n", " You can use the `timeit` module and the `timeit` Jupyter magic for more accurate benchmarking. Documentation on these can be found here.\n", "