Skip to main content

pick a meeting time

Project description

Undertime - pick a meeting time

This program allows you to quickly pick a meeting time across multiple timezones for conference calls or other coordinated events. It shows all times of a given day for all the timezones selected, in a table that aligns the time so a line shows simultaneous times across all timezones. This takes into account daylight savings and other peculiarities (provided that the local timezone database is up to date) so you can also schedule meetings in the future as well.

screenshot of undertime computing possible meeting time for multiple timezones on a daylight savings switch in the America/Vancouver, America/New_York, UTC and Europe/Paris timezones Say thanks to the author

Usage

Timezones should be passed on the commandline and are matched against the list of known timezones, as defined by the pytz package. Exact matches are attempted at first, but if that fails, substring matches are allowed, which makes it possible to do this:

undertime --timezones New_York Los_Angeles

Example output:

ananarcat@angela:undertime$ ./undertime --no-colors --config=undertime.yml --no-default-zone
╔═════════════╤════════════╤════════╤═════════╤═══════════════╤═════════════╤════════════╤═════╗
║  Vancouver  │  New_York  │  UTC   │  Paris  │  Addis_Ababa  │  Hong_Kong  │  Auckland  │   n ║
╠═════════════╪════════════╪════════╪═════════╪═══════════════╪═════════════╪════════════╪═════╣
║    21:00    │   00:00    │ 05:00  │  06:00  │     08:00     │   13:00_    │   18:00    │   1 ║
║    22:00    │   01:00    │ 06:00  │  07:00  │    09:00_     │   14:00_    │   19:00    │   2 ║
║    23:00    │   02:00    │ 07:00  │  08:00  │    10:00_     │   15:00_    │   20:00    │   2 ║
║    00:00    │   03:00    │ 08:00  │ 09:00_  │    11:00_     │   16:00_    │   21:00    │   3 ║
║    01:00    │   04:00    │ 09:00_ │ 10:00_  │    12:00_     │   17:00_    │   22:00    │   4 ║
║    02:00    │   05:00    │ 10:00_ │ 11:00_  │    13:00_     │    18:00    │   23:00    │   3 ║
║    03:00    │   06:00    │ 11:00_ │ 12:00_  │    14:00_     │    19:00    │   00:00    │   3 ║
║    04:00    │   07:00    │ 12:00_ │ 13:00_  │    15:00_     │    20:00    │   01:00    │   3 ║
║    05:00    │   08:00    │ 13:00_ │ 14:00_  │    16:00_     │    21:00    │   02:00    │   3 ║
║    06:00    │   09:00_   │ 14:00_ │ 15:00_  │    17:00_     │    22:00    │   03:00    │   4 ║
║    07:00    │   10:00_   │ 15:00_ │ 16:00_  │     18:00     │    23:00    │   04:00    │   3 ║
║    08:00    │   11:00_   │ 16:00_ │ 17:00_  │     19:00     │    00:00    │   05:00    │   3 ║
║   09:00_    │   12:00_   │ 17:00_ │  18:00  │     20:00     │    01:00    │   06:00    │   3 ║
║   10:00_    │   13:00_   │ 18:00  │  19:00  │     21:00     │    02:00    │   07:00    │   2 ║
║   11:00_    │   14:00_   │ 19:00  │  20:00  │     22:00     │    03:00    │   08:00    │   2 ║
║   12:00_    │   15:00_   │ 20:00  │  21:00  │     23:00     │    04:00    │   09:00_   │   3 ║
║   13:00_    │   16:00_   │ 21:00  │  22:00  │     00:00     │    05:00    │   10:00_   │   3 ║
║   14:00_    │   17:00_   │ 22:00  │  23:00  │     01:00     │    06:00    │   11:00_   │   3 ║
║   14:07*    │   17:07*   │ 22:07* │ 23:07*  │    01:07*     │   06:07*    │   11:07*   │   3 ║
║   15:00_    │   18:00    │ 23:00  │  00:00  │     02:00     │    07:00    │   12:00_   │   2 ║
║   16:00_    │   19:00    │ 00:00  │  01:00  │     03:00     │    08:00    │   13:00_   │   2 ║
║   17:00_    │   20:00    │ 01:00  │  02:00  │     04:00     │   09:00_    │   14:00_   │   3 ║
║    18:00    │   21:00    │ 02:00  │  03:00  │     05:00     │   10:00_    │   15:00_   │   2 ║
║    19:00    │   22:00    │ 03:00  │  04:00  │     06:00     │   11:00_    │   16:00_   │   2 ║
║    20:00    │   23:00    │ 04:00  │  05:00  │     07:00     │   12:00_    │   17:00_   │   2 ║
╚═════════════╧════════════╧════════╧═════════╧═══════════════╧═════════════╧════════════╧═════╝
UTC time: 2025-01-07 22:07:21+00:00
local time: 2025-01-07 17:07:21-05:00
equivalent to:
- 14:07 America/Vancouver
- 17:07 America/New_York
- 22:07 UTC
- 23:07 Europe/Paris
- 2025-01-08 01:07 Africa/Addis_Ababa
- 2025-01-08 06:07 Asia/Hong_Kong
- 2025-01-08 11:07 Pacific/Auckland

In the above, the underscored lines are the ones during the predefined “business hours” range, and the ones with stars are the current time. Those are rendered in yellow and bold, respectively, if colors are enabled.

Because daylight savings may actually change time, you can also specify the time to pick an arbitrary time for the meeting, using natural language (as parsed by the dateparser or parsedatetime modules, if available). The current time is also shown, in bold. This, for example, will show the time “tomorrow” at the same time as today:

undertime tomorrow

Or the next September 21st at 19:00 local time:

undertime September 21 19:00

Colors are used to highlight the “work hours” where possible meeting times could overlap. You can change those work hours with the --start and --end flags. The number of zones matching those hours is listed in the last column.

The output format is controlled by the tabulate program. See the tabulate documentation for more information about the possible outputs.

A configuration file can be used to set defaults, see the undertime.yml file for an example.

The complete list of timezones is also shown when the --list-zones commandline option is provided. Note that in recent tzdata versions, legacy zones like US/Eastern or US/Pacific have been removed, as many others. Install the tzdata-legacy package to restore those.

Also, be careful with those zone names, some are pretty confusing! Etc/GMT+12, for example, is actually UTC-12, confusingly (see this explanation. For people on the american east, you might also be tempted by the EST5EDT zone, hoping it will give you summer time, but it will not do that: pick a summer date and your normal zone (e.g. US/Eastern) and undertime will do the right thing:

> undertime 2024-06-21T12:00:00-0000 --timezones US/Eastern
UTC time: 2024-06-21 12:00:00+00:00
local time: 2024-06-21 08:00:00-04:00
equivalent to: 08:00 US/Eastern

The --list-zones options also shows the offset of each zone, in hours. Note that those are floats: offsets are actually in seconds in the underlying API, but we are trying to save you from this horror. You should be able to sort zones by offset with the sort command:

undertime --list-zones | sort -k2 -n

Finally, note that you can specify zones with a fixed offset with UTC+-N. For example, UTC-12 is Anywhere on Earth. UTC-5 is “normal” (non-daylight) for US/Eastern, but it doesn’t take into account daylight savings, so be careful!

Summary usage is available with the --help flag and full help in the manpage. Instructions for how to contribute to the project are in CONTRIBUTING.rst and there is a CODE_OF_CONDUCT.rst.

Known issues and limitations

Undertime was written using Python 3.5 and 3.7 and there is no guarantee it will work in older (or newer) Python releases.

Timezones – and time in general – are hard problems: the math is hard, and the zones constantly. What may be applicable to your location at the current time may not be reflected by your operating system or the chain of software used by this program to determine time. According to this video from Tom Scott, “you really should never, ever deal with timezones if you can help it”. This sounds a lot like what this program does, but do note that:

“What you learn, after dealing with timezones, is that what you do, is you put away your code, you don’t try and write anything to deal with this. You look at the people who have been there before you. You look at the first people, the people who’ve done this before, the people who’ve built the spaghetti code, and you go to them, and you thank them very much for making it open source, and you give them credit, and you take what they’ve made, you put it in your program. and you never ever look at it again. because that way lies madness.”

—Tom Scott

That is what this program does. It reuses the pytz library based on the Olson tz database. See the Credits section for more information.

Time is an illusion we created to rationalize our unbearable ephemerality and is bound to be imprecise, confusing and flawed. It’s neither your fault or your computer’s: accept and embrace its humanity.

Installing

This program can be installed using pip from the PyPI repository, like so:

pip3 install undertime

The above assumes you’re running a distribution that installs the Python 3 version of pip as pip3, you might need to replace that with just pip on some setups.

This program is also packaged in Debian (since Debian 10 “buster”), so you can also install it with:

apt install undertime

If you downloaded this source code and want to install that directly, you can simply run:

pip3 install .

Credits

This program was written by Antoine Beaupré and is licensed under the AGPLv3+. I rewrote overtime-cli in Python because I felt we shouldn’t need a Javascript virtual machine to pick a time. I was also curious to see how such a rewrite would look like and was tired of loading a web browser every time I needed to figure out what time it was elsewhere in the world or when I needed to coordinate international meetings.

All of this wouldn’t have been possible without the pytz library written by Stuart Bishop, itself based on the Olson tz database founded by Arthur David Olson and currently maintained by Paul Eggert. Those packages are shipped to your favorite Debian distribution by package maintainers who struggle to keep up with those constant changes so credits should also go to the tzdata package maintainers (currently Adam Conrad, Aurelien Jarno, and Clint Adams) along with everyone in the Debian project keeping all those packages up to date. Thank you for dealing with humanity’s confusing, beautiful and complex quirks for all of us.

Similar projects

  • crab fit: web-based, timezone-sensitive meeting planner, free software

  • overtime-cli: primary inspiration for undertime

  • timeanddate.com: what I was using before, non-free

  • tzdiff: strickingly similar, but discovered a few months after writing undertime

  • when: shows time as blocks, Rust, strange syntax (e.g. now in yyz -> sfo -> lhr), not updated in 3 years as of 2025

  • worldchatclock.com: beautiful round, web interface, non-free

  • worldtimebuddy.com: simple web interface, clever horizontal design, non-free

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

undertime-4.3.0-py3-none-any.whl (34.6 kB view details)

Uploaded Python 3

File details

Details for the file undertime-4.3.0-py3-none-any.whl.

File metadata

  • Download URL: undertime-4.3.0-py3-none-any.whl
  • Upload date:
  • Size: 34.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for undertime-4.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c1a807c7395acaaf9691f008fbc59542b9cfc4a0b4bd6ef398276b29f3b745a
MD5 b9ed521b08b132d163c804fbb6ead194
BLAKE2b-256 cb05cc71c71a1476c5452883b5636bd8eb43f266f064afa0819335092611e1b0

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page