when


Namewhen JSON
Version 3.3 PyPI version JSON
download
home_pageNone
SummaryCalculate and convert times across time zones and cities of significant population
upload_time2025-02-07 18:39:55
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT License Copyright (c) 2024 David A Krauth Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
keywords time timezone timezones
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # when πŸŒπŸ•

[![Tests](https://github.com/dakrauth/when/actions/workflows/test.yml/badge.svg)](https://github.com/dakrauth/when)
[![PyPI](https://img.shields.io/pypi/v/when.svg)](https://pypi.python.org/pypi/when)

**Scenario:** Your favorite sporting event, concert, performance, conference, or symposium is happening
in Ulan Bator, Mongolia and all you have is the time of the event relative to the location -- Feb 8, 3pm.

* What time is it currently in Ulan Bator?

  ```console
  $ when --source "Ulan Bator"
  2025-02-07 03:08:58+0800 (+08, Asia/Ulaanbaatar) 038d05w (Ulan Bator, Ulaanbaatar, MN, Asia/Ulaanbaatar)[πŸŒ“ First Quarter]
  ```
* What time is the event in your local time (PST for me, currently)?

  ```console
  $ when --source "Ulan Bator" Feb 8 3pm
  2025-02-07 23:00:00-0800 (PST, America/Los_Angeles) 038d05w [πŸŒ“ First Quarter]
  ```

* What time did it or will it occur at some other time, past or present?

  ```console
  $ when --source "Ulan Bator" --offset +15d6h
  2025-02-22 09:18:01+0800 (+08, Asia/Ulaanbaatar) 053d07w (Ulan Bator, Ulaanbaatar, MN, Asia/Ulaanbaatar)[πŸŒ— Last Quarter]
  ```
* What about for your friends in other locations around the world?

  ```console
  $ when --exact --target London,GB  --source "Ulan Bator" Feb 8 3pm
  2025-02-08 07:00:00+0000 (GMT, Europe/London) 039d05w (London, England, GB, Europe/London)[πŸŒ“ First Quarter]
  ```

## Table of Contents

- [Features](#features)
- [Installation](#installation)
  - [Database Installation](#database-installation)
- [Examples](#examples)
  - [Basic Usage](#basic-usage)
  - [Formats](#formats)
  - [Timezones](#timezones)
  - [Cities](#cities)
  - [Database Search](#database-search)
  - [Database Aliases](#database-aliases)
  - [Source Input Times](#source-input-times)
  - [Targets](#targets)
  - [JSON](#json)
  - [Holidays](#holidays)
  - [Full Moons](#full-moons)
- [Formatting](#formatting)
- [Configuration](#configuration)
  - [Default TOML](#default-toml)
- [Complete CLI Options](#complete-cli-options)
- [Development](#development)

## Features

``when`` can refer to source and target locations via the ``--source`` and ``--target`` specifiers.

* πŸ™οΈ ``when`` can download a [GeoNames](https://www.geonames.org/export/) cities database for referencing locations by city name
* πŸ•˜ All IANA time zone definitions are available, as well as the most common time zone aliases (i.e.: ``EST`` => ``US/Eastern``).
  For further reading, see [Time Zones Aren’t Offsets – Offsets Aren’t Time Zones](https://spin.atomicobject.com/time-zones-offsets/)
* πŸŒ– Display current lunar state
* πŸŽ‰ List common holidays for a given country and/or year (US or configurable)
* 🌝 Show dates for full moons
* βš™οΈ Extensive configuration options for results
* πŸ“„ JSON output
* πŸ—“οΈ Allow for past and future offsets
* πŸ”Ž 96% test code coverage


## Installation

> **Requirements**
>
> _Python 3.10+ or pipx_


* Install from [PyPI](https://pypi.org/project/when/):

  ```console
  $ pip install when
  ```
* Install using [`pipx`](https://pypa.github.io/pipx/):

  ```console
  $ pipx install when
  ```
  or:
  ```console
  $ pipx install git+https://github.com/dakrauth/when.git
  ```
* Install from [GitHub source](https://github.com/dakrauth/when)

  ```console
  git clone git@github.com:dakrauth/when.git
  python -m pip install --require-virtualenv when/
  ```
  See [Development](#development) below for detailed instructions for working on `when` below.

> **Note**
>
> _Once installed, if you wish to utilize ``when``'s full capabilities, you should install the GeoNames cities database as describe next._

### Database installation

To access city names, you need to install the cities database after installing the ``when`` application:

```console
$ when --db <SIZE> [options]
```

Use the ``<SIZE>`` option to specify a database download size. For detailed info, see the
[GeoNames ReadMe](https://download.geonames.org/export/dump/readme.txt).

``<SIZE>`` options must be one of the following:

* ``sm``: ~2.9M download, ~2M DB
  * All country capitals
  * Cities with population > 15,000
* ``md``: **_default_** ~4.8M download, ~3.1M DB; same as ``sm``, plus:
  * Seat of first-order admin division, i.e. US state
  * Cities with population > 5,000
* ``lg``: ~9.5M download, ~5.8M DB; same as ``md``, plus:
  * seat of admin division down to third level (counties)
  * cities with population > 1,000
* ``xl`` ~12.1M download, ~7.2M DB;  same as ``lg``, plus:
  * seat of admin division down to fourth order 
  * cities with population > 500


Additional ``options`` are:

* ``--db-pop``: Filter non-admin division seats providing a minimum city population size
* ``--force``: Force an existing database to be overwritten

## Examples

### Basic Usage

> **Note**
>
> _In the following examples, please the ``xl`` database has been installed, and that the system ``TZ`` is configured for the West coast of the NW United States._

The most basic form of `when` will show the following output, based upon the system's date and timezone configuration:

```console
$ when
2025-02-04 17:38:10-0800 (PST, America/Los_Angeles) 035d05w [πŸŒ’ Waxing Crescent]
```

### Formats

The default format of the output is structured as:

```<ISO 8601 timestamp> (<TZ abbreviation>, <TZ name>) <Day-if-year>d<Week-of-year>w [<Lunar information>]```

The default format configuration is specified by the string `'%F %T%z (%Z%!Z) %jd%Ww %!C[%!l]'`.

Output formatting can be configured in multiple ways:

* Creating a `.whenrc.toml` configuration file (see [Configuration](#configuration) below)
* Use the `--format` option and use formatting pattern (see [Formatting](#formatting) below):

  ```console
  $ when --format '%a %b %d %Y %T %!c' --source Seattle
  Tue Feb 04 2025 17:40:11 Seattle, Washington, US, America/Los_Angeles
  ```

* Use one of the pre-configured, named formats such as `iso` and `rfc2822`:

  ```console
  $ when --format iso
  2025-02-05T16:31:22-0800
  
  $ when --format rfc2822
  Wed, 05 Feb 2025 16:31:30 -0800
  ```

* Set a ``WHENFORMAT`` env variable, which can specified in your with your shell config (such as ``.bash_prole`` or ``.zshrc``),
  or prepended to the command line command, for instance:

  ```console
  $ WHENFORMAT='%a %b %d %Y %T %!c' when --source Seattle
  Tue Feb 04 2025 17:40:09 Seattle, Washington, US, America/Los_Angeles
  ```

### Timezones

Source (and target) locations can also be specified by IANA timezone names or aliases:

```console
$ when --source CST
2025-02-04 20:01:43-0600 (CST, Central Standard Time) 035d05w [πŸŒ’ Waxing Crescent]
2025-02-05 06:01:43+0400 (+04, Caucasus Standard Time) 036d05w [πŸŒ“ First Quarter]
2025-02-05 10:01:43+0800 (CST, China Standard Time) 036d05w [πŸŒ“ First Quarter]
2025-02-04 21:01:43-0500 (CST, Cuba Standard Time) 035d05w [πŸŒ’ Waxing Crescent]
```

### Cities

Searching by city can return numerous results, since by default the database is queried looking
for matches __containing__ the search string:

```console
$ when --source Paris
2025-02-05 04:04:44+0200 (EET, Europe/Athens) 036d05w (KyparissΓ­a (Kyparissia), Peloponnese, GR, Europe/Athens)[πŸŒ“ First Quarter]
2025-02-05 02:04:44+0000 (GMT, Europe/London) 036d05w (Whiteparish, England, GB, Europe/London)[πŸŒ“ First Quarter]
2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Villeparisis, Île-de-France, FR, Europe/Paris)[πŸŒ“ First Quarter]
2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Seyssinet-Pariset, Auvergne-RhΓ΄ne-Alpes, FR, Europe/Paris)[πŸŒ“ First Quarter]
2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Paris, Île-de-France, FR, Europe/Paris)[πŸŒ“ First Quarter]
2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Cormeilles-en-Parisis, Île-de-France, FR, Europe/Paris)[πŸŒ“ First Quarter]
...
2025-02-04 20:04:44-0600 (CST, America/Chicago) 035d05w (Paris, Texas, US, America/Chicago)[πŸŒ’ Waxing Crescent]
2025-02-04 21:04:44-0500 (EST, America/New_York) 035d05w (Paris, Maine, US, America/New_York)[πŸŒ’ Waxing Crescent]
2025-02-04 19:04:44-0700 (MST, America/Boise) 035d05w (Paris, Idaho, US, America/Boise)[πŸŒ’ Waxing Crescent]
2025-02-04 21:04:44-0500 (EST, America/Toronto) 035d05w (Paris, Ontario, CA, America/Toronto)[πŸŒ’ Waxing Crescent]
2025-02-05 09:04:44+0700 (WIB, Asia/Jakarta) 036d05w (Danauparis, Aceh, ID, Asia/Jakarta)[πŸŒ“ First Quarter]
```

Use ``--exact`` to restrict the results to a full match on the respective columns within the database:

```console
$ when --exact --source paris
2025-02-05 03:09:24+0100 (CET, Europe/Paris) 036d05w (Paris, Île-de-France, FR, Europe/Paris)[πŸŒ“ First Quarter]
2025-02-04 21:09:24-0500 (EST, America/Panama) 035d05w (ParΓ­s (Paris), Herrera Province, PA, America/Panama)[πŸŒ’ Waxing Crescent]
2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Illinois, US, America/Chicago)[πŸŒ’ Waxing Crescent]
2025-02-04 21:09:24-0500 (EST, America/New_York) 035d05w (Paris, Kentucky, US, America/New_York)[πŸŒ’ Waxing Crescent]
2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Missouri, US, America/Chicago)[πŸŒ’ Waxing Crescent]
2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Tennessee, US, America/Chicago)[πŸŒ’ Waxing Crescent]
2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Texas, US, America/Chicago)[πŸŒ’ Waxing Crescent]
2025-02-04 21:09:24-0500 (EST, America/New_York) 035d05w (Paris, Maine, US, America/New_York)[πŸŒ’ Waxing Crescent]
2025-02-04 19:09:24-0700 (MST, America/Boise) 035d05w (Paris, Idaho, US, America/Boise)[πŸŒ’ Waxing Crescent]
2025-02-04 21:09:24-0500 (EST, America/Toronto) 035d05w (Paris, Ontario, CA, America/Toronto)[πŸŒ’ Waxing Crescent]
```

You can also filter by country:

```console
$ when --exact --source paris,fr
2025-02-05 03:10:17+0100 (CET, Europe/Paris) 036d05w (Paris, Île-de-France, FR, Europe/Paris)[πŸŒ“ First Quarter]
```

Or by subnational region (e.g. a state in the US):

```console
$ when --exact --source paris,maine,us
2025-02-04 21:11:13-0500 (EST, America/New_York) 035d05w (Paris, Maine, US, America/New_York)[πŸŒ’ Waxing Crescent]
```

### Database Search

Use ``--search`` to search the GeoNames database, once installed:

```console
$ when --search paris
 259782 KyparissΓ­a (Kyparissia), Peloponnese, GR, Europe/Athens
2634065 Whiteparish, England, GB, Europe/London
2968496 Villeparisis, Île-de-France, FR, Europe/Paris
2974645 Seyssinet-Pariset, Auvergne-RhΓ΄ne-Alpes, FR, Europe/Paris
2988507 Paris, Île-de-France, FR, Europe/Paris
3023645 Cormeilles-en-Parisis, Île-de-France, FR, Europe/Paris
3703358 ParΓ­s (Paris), Herrera Province, PA, America/Panama
3725276 Fond Parisien, Ouest, HT, America/Port-au-Prince
4246659 Paris, Illinois, US, America/Chicago
4303602 Paris, Kentucky, US, America/New_York
4402452 Paris, Missouri, US, America/Chicago
4647963 Paris, Tennessee, US, America/Chicago
4717560 Paris, Texas, US, America/Chicago
4974617 Paris, Maine, US, America/New_York
5603240 Paris, Idaho, US, America/Boise
6942553 Paris, Ontario, CA, America/Toronto
8571689 Danauparis, Aceh, ID, Asia/Jakarta
```

Results of a database search are formated as:

```<GeoName ID> <Name> [(<ASCII Name>)], <Subregion>, <Country code>, <Timezone info>```

The search feature checks for containment by default, but exact filtering can be useful, as discussed above:

```console
$ when --search paris --exact
2988507 Paris, Île-de-France, FR, Europe/Paris
3703358 ParΓ­s (Paris), Herrera Province, PA, America/Panama
4246659 Paris, Illinois, US, America/Chicago
4303602 Paris, Kentucky, US, America/New_York
4402452 Paris, Missouri, US, America/Chicago
4647963 Paris, Tennessee, US, America/Chicago
4717560 Paris, Texas, US, America/Chicago
4974617 Paris, Maine, US, America/New_York
5603240 Paris, Idaho, US, America/Boise
6942553 Paris, Ontario, CA, America/Toronto
```

### Database Aliases

Use ``--alias`` to add aliases for easier search. For instance, consider the following:

```console
$ when --search "New York City"
5128581 New York City, New York, US, America/New_York
```

If you are checking New York City often, it can be a pain to type out;  however, 
in the result above, we see that New York City has a GeoNames ID of 5128581. You can pass along with the ``--alias`` option along with another name that you would like to use instead:

```console
$ when --alias 5128581 NYC
$ when --source NYC
2025-02-04 21:33:33-0500 (EST, America/New_York) 035d05w (New York City, New York, US, America/New_York)[πŸŒ’ Waxing Crescent]
```

A complete list of aliases can be shown:

```console
$ when --aliases
NYC: New York City | New York | US | America/New_York
```

### Source Input Times

If we know a given time in a specific city or timezone, we can have that converted to our current timezone:

```console
$ when --source Honolulu 17:00
2025-02-04 19:00:00-0800 (PST, America/Los_Angeles) 035d05w [πŸŒ’ Waxing Crescent]
2025-02-04 19:00:00-0800 (PST, America/Los_Angeles) 035d05w [πŸŒ’ Waxing Crescent]
```

**But, wait!** Why are there two results?

Doing a DB search will reveal that there are two entries that could match _Honolulu_:

```console
$ when --search Honolulu
5856195 Honolulu, Hawaii, US, Pacific/Honolulu
7315245 East Honolulu, Hawaii, US, Pacific/Honolulu
```
In this case, ``--exact`` will show only one result:

```console
$ when --exact --source Honolulu 17:00
2025-02-04 19:00:00-0800 (PST, America/Los_Angeles) 035d05w [πŸŒ’ Waxing Crescent]
```
The timestamp string parsing is provided by ``python-dateutil`` and is very generous:

```console
$ when --exact --source Honolulu March 7, 1945 5pm
1945-03-07 19:30:00-0700 (PWT, America/Los_Angeles) 066d10w [🌘 Waning Crescent]
```

### Targets

By default, if the ``--target`` option is not specified, it will default to the local machine's date/time/timezone. However, you can specify another target. For instance, if you are traveling to New York City, and you wish to see when an event occurring in Olso, Norway will be, relatively speaking:

```console
$ when --exact --target NYC --source Oslo June 2 6pm
2025-06-02 12:00:00-0400 (EDT, America/New_York) 153d22w (New York City, New York, US, America/New_York)[πŸŒ’ Waxing Crescent]
```

Notice that details regarding the source (Oslo) are absent. Adding the ``--group`` option will remedy that:

```console
$ when --group --exact --target NYC --source Oslo June 2 6pm
2025-06-02 12:00:00-0400 (EDT, America/New_York) 153d22w (New York City, New York, US, America/New_York)[πŸŒ’ Waxing Crescent]
 ↳ @2025-06-02 18:00:00+0200 (CEST, Europe/Oslo) 153d22w (Oslo, NO, Europe/Oslo)[πŸŒ’ Waxing Crescent]

$ when --exact --source paris,fr --target paris,us --group 21:00
2025-02-04 14:00:00-0600 (CST, America/Chicago) 035d05w (Paris, Illinois, US, America/Chicago)[πŸŒ’ Waxing Crescent]
 ↳ @2025-02-04 21:00:00+0100 (CET, Europe/Paris) 035d05w (Paris, Île-de-France, FR, Europe/Paris)[πŸŒ’ Waxing Crescent]
...
 ↳ @2025-02-04 21:00:00+0100 (CET, Europe/Paris) 035d05w (Paris, Île-de-France, FR, Europe/Paris)[πŸŒ’ Waxing Crescent]
2025-02-04 13:00:00-0700 (MST, America/Boise) 035d05w (Paris, Idaho, US, America/Boise)[πŸŒ’ Waxing Crescent]
 ↳ @2025-02-04 21:00:00+0100 (CET, Europe/Paris) 035d05w (Paris, Île-de-France, FR, Europe/Paris)[πŸŒ’ Waxing Crescent]
```

### JSON

Output can be formatted as `JSON`, e.g., for use in API's:

```console
$ when --exact --json --source Seattle --target Honolulu
[
  {
    "iso": "2025-02-04T17:12:18-10:00",
    "lunar": {
      "emoji": "\ud83c\udf12",
      "phase": "Waxing Crescent",
      "age": 6.545
    },
    "zone": {
      "name": "Pacific/Honolulu",
      "city": {
        "name": "Honolulu",
        "ascii": "Honolulu",
        "country": "US",
        "tz": "Pacific/Honolulu",
        "subnational": "Hawaii"
      },
      "utcoffset": [-10, 0]
    },
    "source": {
      "iso": "2025-02-04T19:12:18-08:00",
      "lunar": {
        "emoji": "\ud83c\udf12",
        "phase": "Waxing Crescent",
        "age": 6.545
      },
      "zone": {
        "name": "America/Los_Angeles",
        "city": {
          "name": "Seattle",
          "ascii": "Seattle",
          "country": "US",
          "tz": "America/Los_Angeles",
          "subnational": "Washington"
        },
        "utcoffset": [-8, 0]
      },
      "source": null,
      "offset": null
    },
    "offset": null
  }
]
```

### Holidays

`when` comes pre-configured with most US holidays:

```console
$ when --holidays US
New Year's Day.....Wed, Jan 01 2025 ( -35 days) [πŸŒ‘ New Moon]
MLK Day............Mon, Jan 20 2025 ( -16 days) [πŸŒ– Waning Gibbous]
Valentine's Day....Fri, Feb 14 2025 (   9 days) [πŸŒ• Full Moon]
Presidents' Day....Mon, Feb 17 2025 (  12 days) [πŸŒ– Waning Gibbous]
Mardi Gras.........Tue, Mar 04 2025 (  27 days) [πŸŒ’ Waxing Crescent]
Ash Wednesday......Wed, Mar 05 2025 (  28 days) [πŸŒ’ Waxing Crescent]
St. Patrick's Day..Mon, Mar 17 2025 (  40 days) [πŸŒ• Full Moon]
Palm Sunday........Sun, Apr 13 2025 (  67 days) [πŸŒ• Full Moon]
Good Friday........Fri, Apr 18 2025 (  72 days) [πŸŒ– Waning Gibbous]
Easter.............Sun, Apr 20 2025 (  74 days) [πŸŒ— Last Quarter]
Mother's Day.......Sun, May 11 2025 (  95 days) [πŸŒ” Waxing Gibbous]
Memorial Day.......Mon, May 26 2025 ( 110 days) [🌘 Waning Crescent]
Father's Day.......Sun, Jun 15 2025 ( 130 days) [πŸŒ– Waning Gibbous]
Juneteenth.........Thu, Jun 19 2025 ( 134 days) [πŸŒ— Last Quarter]
Independence Day...Fri, Jul 04 2025 ( 149 days) [πŸŒ“ First Quarter]
Labor..............Mon, Sep 01 2025 ( 208 days) [πŸŒ“ First Quarter]
Columbus Day.......Mon, Oct 13 2025 ( 250 days) [πŸŒ– Waning Gibbous]
Halloween..........Fri, Oct 31 2025 ( 268 days) [πŸŒ“ First Quarter]
Veterans Day.......Tue, Nov 11 2025 ( 279 days) [πŸŒ– Waning Gibbous]
Thanksgiving.......Thu, Nov 27 2025 ( 295 days) [πŸŒ’ Waxing Crescent]
Christmas..........Thu, Dec 25 2025 ( 323 days) [πŸŒ’ Waxing Crescent]
```

You can specify a year as well:

```console
$ when --holidays US 2026
New Year's Day.....Thu, Jan 01 2026 ( 330 days) [πŸŒ” Waxing Gibbous]
MLK Day............Mon, Jan 19 2026 ( 348 days) [πŸŒ‘ New Moon]
Valentine's Day....Sat, Feb 14 2026 ( 374 days) [🌘 Waning Crescent]
...
Veterans Day.......Wed, Nov 11 2026 ( 644 days) [πŸŒ‘ New Moon]
Thanksgiving.......Thu, Nov 26 2026 ( 659 days) [πŸŒ• Full Moon]
Christmas..........Fri, Dec 25 2026 ( 688 days) [πŸŒ• Full Moon]
```

### Full Moons

```console
$ when --fullmoon
2025-01-13
2025-02-12
2025-03-14
2025-04-12
2025-05-12
2025-06-10
2025-07-10
2025-08-08
2025-09-06
2025-10-06
2025-11-05
2025-12-04
```

You can specify `next`, `prev`, or use `YYY[-MM]`:

```console
$ when --fullmoon next
2025-02-12

$ when --fullmoon prev
2025-01-13

$ when --fullmoon 2026
2026-01-03
2026-02-01
...
2026-11-23
2026-12-23

$ when --fullmoon 2026-01
2026-01-03
```
## Formatting

**Complete listing of specifiers:**

* `%a`: Abbreviated weekday name, `Thu` *
* `%A`: Full weekday name, `Thursday` *
* `%b`: Abbreviated month name, `Aug` *
* `%B`: Full month name, `August` *
* `%c`: Date and time representation, `Thu Aug 23 14:55:02 2001` *
* `%C`: Year divided by 100 and truncated to integer (00-99), `20` †
* `%d`: Day of the month, zero-padded (01-31), `23`
* `%D`: Short MM/DD/YY date, equivalent to `%m/%d/%y`, `08/23/01` †
* `%e`: Day of the month, space-padded ( 1-31), `23` †
* `%F`: Short YYYY-MM-DD date, equivalent to `%Y-%m-%d`, `2001-08-23` †
* `%g`: Week-based year, last two digits (00-99), `01` †
* `%G`: Week-based year, `2001` †
* `%h`: Abbreviated month name (same as `%b`), `Aug` †*
* `%H`: Hour in 24h format (00-23), `14`
* `%I`: Hour in 12h format (01-12), `02`
* `%j`: Day of the year (001-366), `235`
* `%m`: Month as a decimal number (01-12), `08`
* `%M`: Minute (00-59), `55`
* `%n`: New-line character, `\\n` †
* `%p`: AM or PM designation, `PM`
* `%r`: 12-hour clock time, `02:55:02 pm` †*
* `%R`: 24-hour HH:MM time, equivalent to `%H:%M`, `14:55` †
* `%S`: Second (00-61), `02`
* `%t`: Horizontal-tab character, `\\t` †
* `%T`: ISO 8601 time format (HH:MM:SS), equivalent to `%H:%M:%S`, `14:55:02` †
* `%u`: ISO 8601 weekday as number with Monday as 1 (1-7), `4` †
* `%U`: Week number with the first Sunday as the first day of week one (00-53), `33`
* `%V`: ISO 8601 week number (01-53), `34` †
* `%w`: Weekday as a decimal number with Sunday as 0 (0-6), `4`
* `%W`: Week number with the first Monday as the first day of week one (00-53), `34`
* `%x`: Date representation, `08/23/01` *
* `%X`: Time representation, `14:55:02` *
* `%y`: Year, last two digits (00-99), `01`
* `%Y`: Year, `2001`
* `%z`: ISO 8601 offset from UTC in timezone (1 minute=1, 1 hour=100), no characters if timezone cannot be determined `+100`
* `%Z`: Locale timezone name or abbreviation, no characters if timezone cannot be determined `CDT` *
* `%%`: A % sign, `%`
* `%!z`: When timezone name, `US/New_York` ‑
* `%!Z`: When timezone name, using conditional format in settings, `US/New_York` ‑
* `%!c`: City name, `Honolulu, Hawaii, US` ‑
* `%!C`: City name, using conditional format in settings, `Honolulu, Hawaii, US` ‑
* `%!l`: Lunar phase emoji, `πŸŒ–` ‑

† C99 extension | ‑ `when` extension | * Locale-dependent

## Configuration

Configuration is done via [TOML format](https://toml.io/en/) and can be overridden (overlayed, actually)
by creating a `.whenrc.toml` in either the local directory from which `when` is executed, or from
`~/.whenrc.toml`.

To show the current configuration status, you can do:

```console
$ when --config
``` 

You can refer to [Default TOML](#default-toml) below for all configuration values.

To begin, create the file:

```console
$ cat << EOF > .whenrc.toml
[formats.named]
foo = "%x %X"
bar = "%!l"

[formats.source]
grouped = " ➑️ From "
EOF
```

Now, verify the configuration by doing:

```console
$ when --config
``` 

At the top of the output there should be a line similar to the following:

```console
# Read from /path/to/pwd/.whenrc.toml
```

Let's see the result:

```console
$ when --format foo --group --source seattle --target "New York City"
02/05/25 19:02:12
 ➑️ From 02/05/25 16:02:12

$ when --format bar --source seattle
πŸŒ“ First Quarter
```

### Default TOML

```toml
[calendar]
months = [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
days = [ "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]

[holidays]
format = "%a, %b %d %Y"

[lunar]
phases = [ "New Moon", "Waxing Crescent", "First Quarter", "Waxing Gibbous", "Full Moon", "Waning Gibbous", "Last Quarter", "Waning Crescent"]
emojis = "πŸŒ‘πŸŒ’πŸŒ“πŸŒ”πŸŒ•πŸŒ–πŸŒ—πŸŒ˜"
format = "%a, %b %d %Y"

[holidays.US]
Easter = "Easter +0"
"Ash Wednesday" = "Easter -46"
"Mardi Gras" = "Easter -47"
"Palm Sunday" = "Easter -7"
"Good Friday" = "Easter -2"
"Memorial Day" = "Last Mon in May"
"MLK Day" = "3rd Mon in Jan"
"Presidents' Day" = "3rd Mon in Feb"
"Mother's Day" = "2nd Sun in May"
"Father's Day" = "3rd Sun in Jun"
Labor = "1st Mon in Sep"
"Columbus Day" = "2nd Mon in Oct"
Thanksgiving = "4th Thu in Nov"
"New Year's Day" = "Jan 1"
"Valentine's Day" = "Feb 14"
"St. Patrick's Day" = "Mar 17"
Juneteenth = "Jun 19"
"Independence Day" = "Jul 4"
Halloween = "Oct 31"
"Veterans Day" = "Nov 11"
Christmas = "Dec 25"

[formats.named]
default = "%F %T%z (%Z%!Z) %jd%Ww %!C[%!l]"
rfc2822 = "%a, %d %b %Y %H:%M:%S %z"
iso = "%Y-%m-%dT%H:%M:%S%z"

[formats.conditional]
Z = ", {}"
C = "({})"

[formats.source]
grouped = " ↳ @"
```

## Complete CLI Options

```console
usage: when [--delta {long,short}] [--offset [+-]?(\d+wdhm)+] [--prefix] [-s SOURCE] [-t TARGET] [-f FORMAT] [-g] [--all]
            [--holidays COUNTRY_CODE] [-v] [-V] [--json] [--config] [--force] [--search] [--exact] [--alias ALIAS]
            [--aliases] [--db DB] [--db-pop DB_POP] [--tz-alias] [--fullmoon] [-h]
            [timestr ...]

Convert times to and from time zones or cities

positional arguments:
  timestr               Timestamp to parse, defaults to local time

options:
  --delta {long,short}  Show the delta to the given timestamp
  --offset [+-]?(\d+wdhm)+
                        Show the difference from a given offset
  --prefix              Show when's directory
  -s SOURCE, --source SOURCE
                        Timezone / city to convert the timestr from, defaulting to local time
  -t TARGET, --target TARGET
                        Timezone / city to convert the timestr to (globbing patterns allowed, can be comma delimited),
                        defaulting to local time
  -f FORMAT, --format FORMAT
                        Output formatting. Additional formats can be shown using the -v option with -h
  -g, --group           Group sources together under same target results
  --all                 Show times in all common timezones
  --holidays COUNTRY_CODE
                        Show holidays for given country code.
  -v, --verbosity       Verbosity (-v, -vv, etc). Use -v to show `when` extension detailed help
  -V, --version         show program's version number and exit
  --json                Output results in nicely formatted JSON
  --config              Show current configuration settings
  --force               Force an existing database to be overwritten
  --search              Search database for the given city
  --exact               DB searches must be exact
  --alias ALIAS         Create a new alias from the city id
  --aliases             Show all DB aliases
  --db DB               Create cities database from Geonames file. Can be one of 'xl' ('xlarge'), 'lg' ('large'), 'md'
                        ('medium'), 'sm' ('small')
  --db-pop DB_POP       City population minimum.
  --tz-alias            Search for a time zone alias
  --fullmoon            Show full moon(s) for given year or month. Can be in the format of: 'next' | 'prev' | YYYY[-MM]
  -h, --help            Show helpful usage information

Use -v option for details
```

## Development

Requires Python 3.10+ and [just](https://github.com/casey/just) for convenience.

```console
$ git clone git@github.com:dakrauth/when.git
$ cd when
$ just
```

> **Note:**
>
> _``just`` is a shortcut for ``just --help``_

Set up dev env:

```console
$ just init
```

Test, and code coverage:

```console
$ just test
$ just cov
```

Only run a test matching matching a given substring:

```console
$ just test -k test_sometest
```

Run the when command with any arguments:

```console
$ just when --source poulsbo
```

Or, start an interactive session:

```console
$ . ./dev/venv/bin/activate
$ when --help
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "when",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "time, timezone, timezones",
    "author": null,
    "author_email": "David Krauth <dakrauth@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/be/d7/3fe60c5ad35b4cd3773089aa5bdb60cfbf6d76394359a7f1bcdb9d55d2ce/when-3.3.tar.gz",
    "platform": null,
    "description": "# when \ud83c\udf10\ud83d\udd50\n\n[![Tests](https://github.com/dakrauth/when/actions/workflows/test.yml/badge.svg)](https://github.com/dakrauth/when)\n[![PyPI](https://img.shields.io/pypi/v/when.svg)](https://pypi.python.org/pypi/when)\n\n**Scenario:** Your favorite sporting event, concert, performance, conference, or symposium is happening\nin Ulan Bator, Mongolia and all you have is the time of the event relative to the location -- Feb 8, 3pm.\n\n* What time is it currently in Ulan Bator?\n\n  ```console\n  $ when --source \"Ulan Bator\"\n  2025-02-07 03:08:58+0800 (+08, Asia/Ulaanbaatar) 038d05w (Ulan Bator, Ulaanbaatar, MN, Asia/Ulaanbaatar)[\ud83c\udf13 First Quarter]\n  ```\n* What time is the event in your local time (PST for me, currently)?\n\n  ```console\n  $ when --source \"Ulan Bator\" Feb 8 3pm\n  2025-02-07 23:00:00-0800 (PST, America/Los_Angeles) 038d05w [\ud83c\udf13 First Quarter]\n  ```\n\n* What time did it or will it occur at some other time, past or present?\n\n  ```console\n  $ when --source \"Ulan Bator\" --offset +15d6h\n  2025-02-22 09:18:01+0800 (+08, Asia/Ulaanbaatar) 053d07w (Ulan Bator, Ulaanbaatar, MN, Asia/Ulaanbaatar)[\ud83c\udf17 Last Quarter]\n  ```\n* What about for your friends in other locations around the world?\n\n  ```console\n  $ when --exact --target London,GB  --source \"Ulan Bator\" Feb 8 3pm\n  2025-02-08 07:00:00+0000 (GMT, Europe/London) 039d05w (London, England, GB, Europe/London)[\ud83c\udf13 First Quarter]\n  ```\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n  - [Database Installation](#database-installation)\n- [Examples](#examples)\n  - [Basic Usage](#basic-usage)\n  - [Formats](#formats)\n  - [Timezones](#timezones)\n  - [Cities](#cities)\n  - [Database Search](#database-search)\n  - [Database Aliases](#database-aliases)\n  - [Source Input Times](#source-input-times)\n  - [Targets](#targets)\n  - [JSON](#json)\n  - [Holidays](#holidays)\n  - [Full Moons](#full-moons)\n- [Formatting](#formatting)\n- [Configuration](#configuration)\n  - [Default TOML](#default-toml)\n- [Complete CLI Options](#complete-cli-options)\n- [Development](#development)\n\n## Features\n\n``when`` can refer to source and target locations via the ``--source`` and ``--target`` specifiers.\n\n* \ud83c\udfd9\ufe0f ``when`` can download a [GeoNames](https://www.geonames.org/export/) cities database for referencing locations by city name\n* \ud83d\udd58 All IANA time zone definitions are available, as well as the most common time zone aliases (i.e.: ``EST`` => ``US/Eastern``).\n  For further reading, see [Time Zones Aren\u2019t Offsets \u2013 Offsets Aren\u2019t Time Zones](https://spin.atomicobject.com/time-zones-offsets/)\n* \ud83c\udf16 Display current lunar state\n* \ud83c\udf89 List common holidays for a given country and/or year (US or configurable)\n* \ud83c\udf1d Show dates for full moons\n* \u2699\ufe0f Extensive configuration options for results\n* \ud83d\udcc4 JSON output\n* \ud83d\uddd3\ufe0f Allow for past and future offsets\n* \ud83d\udd0e 96% test code coverage\n\n\n## Installation\n\n> **Requirements**\n>\n> _Python 3.10+ or pipx_\n\n\n* Install from [PyPI](https://pypi.org/project/when/):\n\n  ```console\n  $ pip install when\n  ```\n* Install using [`pipx`](https://pypa.github.io/pipx/):\n\n  ```console\n  $ pipx install when\n  ```\n  or:\n  ```console\n  $ pipx install git+https://github.com/dakrauth/when.git\n  ```\n* Install from [GitHub source](https://github.com/dakrauth/when)\n\n  ```console\n  git clone git@github.com:dakrauth/when.git\n  python -m pip install --require-virtualenv when/\n  ```\n  See [Development](#development) below for detailed instructions for working on `when` below.\n\n> **Note**\n>\n> _Once installed, if you wish to utilize ``when``'s full capabilities, you should install the GeoNames cities database as describe next._\n\n### Database installation\n\nTo access city names, you need to install the cities database after installing the ``when`` application:\n\n```console\n$ when --db <SIZE> [options]\n```\n\nUse the ``<SIZE>`` option to specify a database download size. For detailed info, see the\n[GeoNames ReadMe](https://download.geonames.org/export/dump/readme.txt).\n\n``<SIZE>`` options must be one of the following:\n\n* ``sm``: ~2.9M download, ~2M DB\n  * All country capitals\n  * Cities with population > 15,000\n* ``md``: **_default_** ~4.8M download, ~3.1M DB; same as ``sm``, plus:\n  * Seat of first-order admin division, i.e. US state\n  * Cities with population > 5,000\n* ``lg``: ~9.5M download, ~5.8M DB; same as ``md``, plus:\n  * seat of admin division down to third level (counties)\n  * cities with population > 1,000\n* ``xl`` ~12.1M download, ~7.2M DB;  same as ``lg``, plus:\n  * seat of admin division down to fourth order \n  * cities with population > 500\n\n\nAdditional ``options`` are:\n\n* ``--db-pop``: Filter non-admin division seats providing a minimum city population size\n* ``--force``: Force an existing database to be overwritten\n\n## Examples\n\n### Basic Usage\n\n> **Note**\n>\n> _In the following examples, please the ``xl`` database has been installed, and that the system ``TZ`` is configured for the West coast of the NW United States._\n\nThe most basic form of `when` will show the following output, based upon the system's date and timezone configuration:\n\n```console\n$ when\n2025-02-04 17:38:10-0800 (PST, America/Los_Angeles) 035d05w [\ud83c\udf12 Waxing Crescent]\n```\n\n### Formats\n\nThe default format of the output is structured as:\n\n```<ISO 8601 timestamp> (<TZ abbreviation>, <TZ name>) <Day-if-year>d<Week-of-year>w [<Lunar information>]```\n\nThe default format configuration is specified by the string `'%F %T%z (%Z%!Z) %jd%Ww %!C[%!l]'`.\n\nOutput formatting can be configured in multiple ways:\n\n* Creating a `.whenrc.toml` configuration file (see [Configuration](#configuration) below)\n* Use the `--format` option and use formatting pattern (see [Formatting](#formatting) below):\n\n  ```console\n  $ when --format '%a %b %d %Y %T %!c' --source Seattle\n  Tue Feb 04 2025 17:40:11 Seattle, Washington, US, America/Los_Angeles\n  ```\n\n* Use one of the pre-configured, named formats such as `iso` and `rfc2822`:\n\n  ```console\n  $ when --format iso\n  2025-02-05T16:31:22-0800\n  \n  $ when --format rfc2822\n  Wed, 05 Feb 2025 16:31:30 -0800\n  ```\n\n* Set a ``WHENFORMAT`` env variable, which can specified in your with your shell config (such as ``.bash_prole`` or ``.zshrc``),\n  or prepended to the command line command, for instance:\n\n  ```console\n  $ WHENFORMAT='%a %b %d %Y %T %!c' when --source Seattle\n  Tue Feb 04 2025 17:40:09 Seattle, Washington, US, America/Los_Angeles\n  ```\n\n### Timezones\n\nSource (and target) locations can also be specified by IANA timezone names or aliases:\n\n```console\n$ when --source CST\n2025-02-04 20:01:43-0600 (CST, Central Standard Time) 035d05w [\ud83c\udf12 Waxing Crescent]\n2025-02-05 06:01:43+0400 (+04, Caucasus Standard Time) 036d05w [\ud83c\udf13 First Quarter]\n2025-02-05 10:01:43+0800 (CST, China Standard Time) 036d05w [\ud83c\udf13 First Quarter]\n2025-02-04 21:01:43-0500 (CST, Cuba Standard Time) 035d05w [\ud83c\udf12 Waxing Crescent]\n```\n\n### Cities\n\nSearching by city can return numerous results, since by default the database is queried looking\nfor matches __containing__ the search string:\n\n```console\n$ when --source Paris\n2025-02-05 04:04:44+0200 (EET, Europe/Athens) 036d05w (Kypariss\u00eda (Kyparissia), Peloponnese, GR, Europe/Athens)[\ud83c\udf13 First Quarter]\n2025-02-05 02:04:44+0000 (GMT, Europe/London) 036d05w (Whiteparish, England, GB, Europe/London)[\ud83c\udf13 First Quarter]\n2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Villeparisis, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf13 First Quarter]\n2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Seyssinet-Pariset, Auvergne-Rh\u00f4ne-Alpes, FR, Europe/Paris)[\ud83c\udf13 First Quarter]\n2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Paris, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf13 First Quarter]\n2025-02-05 03:04:44+0100 (CET, Europe/Paris) 036d05w (Cormeilles-en-Parisis, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf13 First Quarter]\n...\n2025-02-04 20:04:44-0600 (CST, America/Chicago) 035d05w (Paris, Texas, US, America/Chicago)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 21:04:44-0500 (EST, America/New_York) 035d05w (Paris, Maine, US, America/New_York)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 19:04:44-0700 (MST, America/Boise) 035d05w (Paris, Idaho, US, America/Boise)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 21:04:44-0500 (EST, America/Toronto) 035d05w (Paris, Ontario, CA, America/Toronto)[\ud83c\udf12 Waxing Crescent]\n2025-02-05 09:04:44+0700 (WIB, Asia/Jakarta) 036d05w (Danauparis, Aceh, ID, Asia/Jakarta)[\ud83c\udf13 First Quarter]\n```\n\nUse ``--exact`` to restrict the results to a full match on the respective columns within the database:\n\n```console\n$ when --exact --source paris\n2025-02-05 03:09:24+0100 (CET, Europe/Paris) 036d05w (Paris, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf13 First Quarter]\n2025-02-04 21:09:24-0500 (EST, America/Panama) 035d05w (Par\u00eds (Paris), Herrera Province, PA, America/Panama)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Illinois, US, America/Chicago)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 21:09:24-0500 (EST, America/New_York) 035d05w (Paris, Kentucky, US, America/New_York)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Missouri, US, America/Chicago)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Tennessee, US, America/Chicago)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 20:09:24-0600 (CST, America/Chicago) 035d05w (Paris, Texas, US, America/Chicago)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 21:09:24-0500 (EST, America/New_York) 035d05w (Paris, Maine, US, America/New_York)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 19:09:24-0700 (MST, America/Boise) 035d05w (Paris, Idaho, US, America/Boise)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 21:09:24-0500 (EST, America/Toronto) 035d05w (Paris, Ontario, CA, America/Toronto)[\ud83c\udf12 Waxing Crescent]\n```\n\nYou can also filter by country:\n\n```console\n$ when --exact --source paris,fr\n2025-02-05 03:10:17+0100 (CET, Europe/Paris) 036d05w (Paris, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf13 First Quarter]\n```\n\nOr by subnational region (e.g. a state in the US):\n\n```console\n$ when --exact --source paris,maine,us\n2025-02-04 21:11:13-0500 (EST, America/New_York) 035d05w (Paris, Maine, US, America/New_York)[\ud83c\udf12 Waxing Crescent]\n```\n\n### Database Search\n\nUse ``--search`` to search the GeoNames database, once installed:\n\n```console\n$ when --search paris\n 259782 Kypariss\u00eda (Kyparissia), Peloponnese, GR, Europe/Athens\n2634065 Whiteparish, England, GB, Europe/London\n2968496 Villeparisis, \u00cele-de-France, FR, Europe/Paris\n2974645 Seyssinet-Pariset, Auvergne-Rh\u00f4ne-Alpes, FR, Europe/Paris\n2988507 Paris, \u00cele-de-France, FR, Europe/Paris\n3023645 Cormeilles-en-Parisis, \u00cele-de-France, FR, Europe/Paris\n3703358 Par\u00eds (Paris), Herrera Province, PA, America/Panama\n3725276 Fond Parisien, Ouest, HT, America/Port-au-Prince\n4246659 Paris, Illinois, US, America/Chicago\n4303602 Paris, Kentucky, US, America/New_York\n4402452 Paris, Missouri, US, America/Chicago\n4647963 Paris, Tennessee, US, America/Chicago\n4717560 Paris, Texas, US, America/Chicago\n4974617 Paris, Maine, US, America/New_York\n5603240 Paris, Idaho, US, America/Boise\n6942553 Paris, Ontario, CA, America/Toronto\n8571689 Danauparis, Aceh, ID, Asia/Jakarta\n```\n\nResults of a database search are formated as:\n\n```<GeoName ID> <Name> [(<ASCII Name>)], <Subregion>, <Country code>, <Timezone info>```\n\nThe search feature checks for containment by default, but exact filtering can be useful, as discussed above:\n\n```console\n$ when --search paris --exact\n2988507 Paris, \u00cele-de-France, FR, Europe/Paris\n3703358 Par\u00eds (Paris), Herrera Province, PA, America/Panama\n4246659 Paris, Illinois, US, America/Chicago\n4303602 Paris, Kentucky, US, America/New_York\n4402452 Paris, Missouri, US, America/Chicago\n4647963 Paris, Tennessee, US, America/Chicago\n4717560 Paris, Texas, US, America/Chicago\n4974617 Paris, Maine, US, America/New_York\n5603240 Paris, Idaho, US, America/Boise\n6942553 Paris, Ontario, CA, America/Toronto\n```\n\n### Database Aliases\n\nUse ``--alias`` to add aliases for easier search. For instance, consider the following:\n\n```console\n$ when --search \"New York City\"\n5128581 New York City, New York, US, America/New_York\n```\n\nIf you are checking New York City often, it can be a pain to type out;  however, \nin the result above, we see that New York City has a GeoNames ID of 5128581. You can pass along with the ``--alias`` option along with another name that you would like to use instead:\n\n```console\n$ when --alias 5128581 NYC\n$ when --source NYC\n2025-02-04 21:33:33-0500 (EST, America/New_York) 035d05w (New York City, New York, US, America/New_York)[\ud83c\udf12 Waxing Crescent]\n```\n\nA complete list of aliases can be shown:\n\n```console\n$ when --aliases\nNYC: New York City | New York | US | America/New_York\n```\n\n### Source Input Times\n\nIf we know a given time in a specific city or timezone, we can have that converted to our current timezone:\n\n```console\n$ when --source Honolulu 17:00\n2025-02-04 19:00:00-0800 (PST, America/Los_Angeles) 035d05w [\ud83c\udf12 Waxing Crescent]\n2025-02-04 19:00:00-0800 (PST, America/Los_Angeles) 035d05w [\ud83c\udf12 Waxing Crescent]\n```\n\n**But, wait!** Why are there two results?\n\nDoing a DB search will reveal that there are two entries that could match _Honolulu_:\n\n```console\n$ when --search Honolulu\n5856195 Honolulu, Hawaii, US, Pacific/Honolulu\n7315245 East Honolulu, Hawaii, US, Pacific/Honolulu\n```\nIn this case, ``--exact`` will show only one result:\n\n```console\n$ when --exact --source Honolulu 17:00\n2025-02-04 19:00:00-0800 (PST, America/Los_Angeles) 035d05w [\ud83c\udf12 Waxing Crescent]\n```\nThe timestamp string parsing is provided by ``python-dateutil`` and is very generous:\n\n```console\n$ when --exact --source Honolulu March 7, 1945 5pm\n1945-03-07 19:30:00-0700 (PWT, America/Los_Angeles) 066d10w [\ud83c\udf18 Waning Crescent]\n```\n\n### Targets\n\nBy default, if the ``--target`` option is not specified, it will default to the local machine's date/time/timezone. However, you can specify another target. For instance, if you are traveling to New York City, and you wish to see when an event occurring in Olso, Norway will be, relatively speaking:\n\n```console\n$ when --exact --target NYC --source Oslo June 2 6pm\n2025-06-02 12:00:00-0400 (EDT, America/New_York) 153d22w (New York City, New York, US, America/New_York)[\ud83c\udf12 Waxing Crescent]\n```\n\nNotice that details regarding the source (Oslo) are absent. Adding the ``--group`` option will remedy that:\n\n```console\n$ when --group --exact --target NYC --source Oslo June 2 6pm\n2025-06-02 12:00:00-0400 (EDT, America/New_York) 153d22w (New York City, New York, US, America/New_York)[\ud83c\udf12 Waxing Crescent]\n \u21b3 @2025-06-02 18:00:00+0200 (CEST, Europe/Oslo) 153d22w (Oslo, NO, Europe/Oslo)[\ud83c\udf12 Waxing Crescent]\n\n$ when --exact --source paris,fr --target paris,us --group 21:00\n2025-02-04 14:00:00-0600 (CST, America/Chicago) 035d05w (Paris, Illinois, US, America/Chicago)[\ud83c\udf12 Waxing Crescent]\n \u21b3 @2025-02-04 21:00:00+0100 (CET, Europe/Paris) 035d05w (Paris, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf12 Waxing Crescent]\n...\n \u21b3 @2025-02-04 21:00:00+0100 (CET, Europe/Paris) 035d05w (Paris, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf12 Waxing Crescent]\n2025-02-04 13:00:00-0700 (MST, America/Boise) 035d05w (Paris, Idaho, US, America/Boise)[\ud83c\udf12 Waxing Crescent]\n \u21b3 @2025-02-04 21:00:00+0100 (CET, Europe/Paris) 035d05w (Paris, \u00cele-de-France, FR, Europe/Paris)[\ud83c\udf12 Waxing Crescent]\n```\n\n### JSON\n\nOutput can be formatted as `JSON`, e.g., for use in API's:\n\n```console\n$ when --exact --json --source Seattle --target Honolulu\n[\n  {\n    \"iso\": \"2025-02-04T17:12:18-10:00\",\n    \"lunar\": {\n      \"emoji\": \"\\ud83c\\udf12\",\n      \"phase\": \"Waxing Crescent\",\n      \"age\": 6.545\n    },\n    \"zone\": {\n      \"name\": \"Pacific/Honolulu\",\n      \"city\": {\n        \"name\": \"Honolulu\",\n        \"ascii\": \"Honolulu\",\n        \"country\": \"US\",\n        \"tz\": \"Pacific/Honolulu\",\n        \"subnational\": \"Hawaii\"\n      },\n      \"utcoffset\": [-10, 0]\n    },\n    \"source\": {\n      \"iso\": \"2025-02-04T19:12:18-08:00\",\n      \"lunar\": {\n        \"emoji\": \"\\ud83c\\udf12\",\n        \"phase\": \"Waxing Crescent\",\n        \"age\": 6.545\n      },\n      \"zone\": {\n        \"name\": \"America/Los_Angeles\",\n        \"city\": {\n          \"name\": \"Seattle\",\n          \"ascii\": \"Seattle\",\n          \"country\": \"US\",\n          \"tz\": \"America/Los_Angeles\",\n          \"subnational\": \"Washington\"\n        },\n        \"utcoffset\": [-8, 0]\n      },\n      \"source\": null,\n      \"offset\": null\n    },\n    \"offset\": null\n  }\n]\n```\n\n### Holidays\n\n`when` comes pre-configured with most US holidays:\n\n```console\n$ when --holidays US\nNew Year's Day.....Wed, Jan 01 2025 ( -35 days) [\ud83c\udf11 New Moon]\nMLK Day............Mon, Jan 20 2025 ( -16 days) [\ud83c\udf16 Waning Gibbous]\nValentine's Day....Fri, Feb 14 2025 (   9 days) [\ud83c\udf15 Full Moon]\nPresidents' Day....Mon, Feb 17 2025 (  12 days) [\ud83c\udf16 Waning Gibbous]\nMardi Gras.........Tue, Mar 04 2025 (  27 days) [\ud83c\udf12 Waxing Crescent]\nAsh Wednesday......Wed, Mar 05 2025 (  28 days) [\ud83c\udf12 Waxing Crescent]\nSt. Patrick's Day..Mon, Mar 17 2025 (  40 days) [\ud83c\udf15 Full Moon]\nPalm Sunday........Sun, Apr 13 2025 (  67 days) [\ud83c\udf15 Full Moon]\nGood Friday........Fri, Apr 18 2025 (  72 days) [\ud83c\udf16 Waning Gibbous]\nEaster.............Sun, Apr 20 2025 (  74 days) [\ud83c\udf17 Last Quarter]\nMother's Day.......Sun, May 11 2025 (  95 days) [\ud83c\udf14 Waxing Gibbous]\nMemorial Day.......Mon, May 26 2025 ( 110 days) [\ud83c\udf18 Waning Crescent]\nFather's Day.......Sun, Jun 15 2025 ( 130 days) [\ud83c\udf16 Waning Gibbous]\nJuneteenth.........Thu, Jun 19 2025 ( 134 days) [\ud83c\udf17 Last Quarter]\nIndependence Day...Fri, Jul 04 2025 ( 149 days) [\ud83c\udf13 First Quarter]\nLabor..............Mon, Sep 01 2025 ( 208 days) [\ud83c\udf13 First Quarter]\nColumbus Day.......Mon, Oct 13 2025 ( 250 days) [\ud83c\udf16 Waning Gibbous]\nHalloween..........Fri, Oct 31 2025 ( 268 days) [\ud83c\udf13 First Quarter]\nVeterans Day.......Tue, Nov 11 2025 ( 279 days) [\ud83c\udf16 Waning Gibbous]\nThanksgiving.......Thu, Nov 27 2025 ( 295 days) [\ud83c\udf12 Waxing Crescent]\nChristmas..........Thu, Dec 25 2025 ( 323 days) [\ud83c\udf12 Waxing Crescent]\n```\n\nYou can specify a year as well:\n\n```console\n$ when --holidays US 2026\nNew Year's Day.....Thu, Jan 01 2026 ( 330 days) [\ud83c\udf14 Waxing Gibbous]\nMLK Day............Mon, Jan 19 2026 ( 348 days) [\ud83c\udf11 New Moon]\nValentine's Day....Sat, Feb 14 2026 ( 374 days) [\ud83c\udf18 Waning Crescent]\n...\nVeterans Day.......Wed, Nov 11 2026 ( 644 days) [\ud83c\udf11 New Moon]\nThanksgiving.......Thu, Nov 26 2026 ( 659 days) [\ud83c\udf15 Full Moon]\nChristmas..........Fri, Dec 25 2026 ( 688 days) [\ud83c\udf15 Full Moon]\n```\n\n### Full Moons\n\n```console\n$ when --fullmoon\n2025-01-13\n2025-02-12\n2025-03-14\n2025-04-12\n2025-05-12\n2025-06-10\n2025-07-10\n2025-08-08\n2025-09-06\n2025-10-06\n2025-11-05\n2025-12-04\n```\n\nYou can specify `next`, `prev`, or use `YYY[-MM]`:\n\n```console\n$ when --fullmoon next\n2025-02-12\n\n$ when --fullmoon prev\n2025-01-13\n\n$ when --fullmoon 2026\n2026-01-03\n2026-02-01\n...\n2026-11-23\n2026-12-23\n\n$ when --fullmoon 2026-01\n2026-01-03\n```\n## Formatting\n\n**Complete listing of specifiers:**\n\n* `%a`: Abbreviated weekday name, `Thu` *\n* `%A`: Full weekday name, `Thursday` *\n* `%b`: Abbreviated month name, `Aug` *\n* `%B`: Full month name, `August` *\n* `%c`: Date and time representation, `Thu Aug 23 14:55:02 2001` *\n* `%C`: Year divided by 100 and truncated to integer (00-99), `20` \u2020\n* `%d`: Day of the month, zero-padded (01-31), `23`\n* `%D`: Short MM/DD/YY date, equivalent to `%m/%d/%y`, `08/23/01` \u2020\n* `%e`: Day of the month, space-padded ( 1-31), `23` \u2020\n* `%F`: Short YYYY-MM-DD date, equivalent to `%Y-%m-%d`, `2001-08-23` \u2020\n* `%g`: Week-based year, last two digits (00-99), `01` \u2020\n* `%G`: Week-based year, `2001` \u2020\n* `%h`: Abbreviated month name (same as `%b`), `Aug` \u2020*\n* `%H`: Hour in 24h format (00-23), `14`\n* `%I`: Hour in 12h format (01-12), `02`\n* `%j`: Day of the year (001-366), `235`\n* `%m`: Month as a decimal number (01-12), `08`\n* `%M`: Minute (00-59), `55`\n* `%n`: New-line character, `\\\\n` \u2020\n* `%p`: AM or PM designation, `PM`\n* `%r`: 12-hour clock time, `02:55:02 pm` \u2020*\n* `%R`: 24-hour HH:MM time, equivalent to `%H:%M`, `14:55` \u2020\n* `%S`: Second (00-61), `02`\n* `%t`: Horizontal-tab character, `\\\\t` \u2020\n* `%T`: ISO 8601 time format (HH:MM:SS), equivalent to `%H:%M:%S`, `14:55:02` \u2020\n* `%u`: ISO 8601 weekday as number with Monday as 1 (1-7), `4` \u2020\n* `%U`: Week number with the first Sunday as the first day of week one (00-53), `33`\n* `%V`: ISO 8601 week number (01-53), `34` \u2020\n* `%w`: Weekday as a decimal number with Sunday as 0 (0-6), `4`\n* `%W`: Week number with the first Monday as the first day of week one (00-53), `34`\n* `%x`: Date representation, `08/23/01` *\n* `%X`: Time representation, `14:55:02` *\n* `%y`: Year, last two digits (00-99), `01`\n* `%Y`: Year, `2001`\n* `%z`: ISO 8601 offset from UTC in timezone (1 minute=1, 1 hour=100), no characters if timezone cannot be determined `+100`\n* `%Z`: Locale timezone name or abbreviation, no characters if timezone cannot be determined `CDT` *\n* `%%`: A % sign, `%`\n* `%!z`: When timezone name, `US/New_York` \u2021\n* `%!Z`: When timezone name, using conditional format in settings, `US/New_York` \u2021\n* `%!c`: City name, `Honolulu, Hawaii, US` \u2021\n* `%!C`: City name, using conditional format in settings, `Honolulu, Hawaii, US` \u2021\n* `%!l`: Lunar phase emoji, `\ud83c\udf16` \u2021\n\n\u2020 C99 extension | \u2021 `when` extension | * Locale-dependent\n\n## Configuration\n\nConfiguration is done via [TOML format](https://toml.io/en/) and can be overridden (overlayed, actually)\nby creating a `.whenrc.toml` in either the local directory from which `when` is executed, or from\n`~/.whenrc.toml`.\n\nTo show the current configuration status, you can do:\n\n```console\n$ when --config\n``` \n\nYou can refer to [Default TOML](#default-toml) below for all configuration values.\n\nTo begin, create the file:\n\n```console\n$ cat << EOF > .whenrc.toml\n[formats.named]\nfoo = \"%x %X\"\nbar = \"%!l\"\n\n[formats.source]\ngrouped = \" \u27a1\ufe0f From \"\nEOF\n```\n\nNow, verify the configuration by doing:\n\n```console\n$ when --config\n``` \n\nAt the top of the output there should be a line similar to the following:\n\n```console\n# Read from /path/to/pwd/.whenrc.toml\n```\n\nLet's see the result:\n\n```console\n$ when --format foo --group --source seattle --target \"New York City\"\n02/05/25 19:02:12\n \u27a1\ufe0f From 02/05/25 16:02:12\n\n$ when --format bar --source seattle\n\ud83c\udf13 First Quarter\n```\n\n### Default TOML\n\n```toml\n[calendar]\nmonths = [ \"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\ndays = [ \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\", \"Sun\"]\n\n[holidays]\nformat = \"%a, %b %d %Y\"\n\n[lunar]\nphases = [ \"New Moon\", \"Waxing Crescent\", \"First Quarter\", \"Waxing Gibbous\", \"Full Moon\", \"Waning Gibbous\", \"Last Quarter\", \"Waning Crescent\"]\nemojis = \"\ud83c\udf11\ud83c\udf12\ud83c\udf13\ud83c\udf14\ud83c\udf15\ud83c\udf16\ud83c\udf17\ud83c\udf18\"\nformat = \"%a, %b %d %Y\"\n\n[holidays.US]\nEaster = \"Easter +0\"\n\"Ash Wednesday\" = \"Easter -46\"\n\"Mardi Gras\" = \"Easter -47\"\n\"Palm Sunday\" = \"Easter -7\"\n\"Good Friday\" = \"Easter -2\"\n\"Memorial Day\" = \"Last Mon in May\"\n\"MLK Day\" = \"3rd Mon in Jan\"\n\"Presidents' Day\" = \"3rd Mon in Feb\"\n\"Mother's Day\" = \"2nd Sun in May\"\n\"Father's Day\" = \"3rd Sun in Jun\"\nLabor = \"1st Mon in Sep\"\n\"Columbus Day\" = \"2nd Mon in Oct\"\nThanksgiving = \"4th Thu in Nov\"\n\"New Year's Day\" = \"Jan 1\"\n\"Valentine's Day\" = \"Feb 14\"\n\"St. Patrick's Day\" = \"Mar 17\"\nJuneteenth = \"Jun 19\"\n\"Independence Day\" = \"Jul 4\"\nHalloween = \"Oct 31\"\n\"Veterans Day\" = \"Nov 11\"\nChristmas = \"Dec 25\"\n\n[formats.named]\ndefault = \"%F %T%z (%Z%!Z) %jd%Ww %!C[%!l]\"\nrfc2822 = \"%a, %d %b %Y %H:%M:%S %z\"\niso = \"%Y-%m-%dT%H:%M:%S%z\"\n\n[formats.conditional]\nZ = \", {}\"\nC = \"({})\"\n\n[formats.source]\ngrouped = \" \u21b3 @\"\n```\n\n## Complete CLI Options\n\n```console\nusage: when [--delta {long,short}] [--offset [+-]?(\\d+wdhm)+] [--prefix] [-s SOURCE] [-t TARGET] [-f FORMAT] [-g] [--all]\n            [--holidays COUNTRY_CODE] [-v] [-V] [--json] [--config] [--force] [--search] [--exact] [--alias ALIAS]\n            [--aliases] [--db DB] [--db-pop DB_POP] [--tz-alias] [--fullmoon] [-h]\n            [timestr ...]\n\nConvert times to and from time zones or cities\n\npositional arguments:\n  timestr               Timestamp to parse, defaults to local time\n\noptions:\n  --delta {long,short}  Show the delta to the given timestamp\n  --offset [+-]?(\\d+wdhm)+\n                        Show the difference from a given offset\n  --prefix              Show when's directory\n  -s SOURCE, --source SOURCE\n                        Timezone / city to convert the timestr from, defaulting to local time\n  -t TARGET, --target TARGET\n                        Timezone / city to convert the timestr to (globbing patterns allowed, can be comma delimited),\n                        defaulting to local time\n  -f FORMAT, --format FORMAT\n                        Output formatting. Additional formats can be shown using the -v option with -h\n  -g, --group           Group sources together under same target results\n  --all                 Show times in all common timezones\n  --holidays COUNTRY_CODE\n                        Show holidays for given country code.\n  -v, --verbosity       Verbosity (-v, -vv, etc). Use -v to show `when` extension detailed help\n  -V, --version         show program's version number and exit\n  --json                Output results in nicely formatted JSON\n  --config              Show current configuration settings\n  --force               Force an existing database to be overwritten\n  --search              Search database for the given city\n  --exact               DB searches must be exact\n  --alias ALIAS         Create a new alias from the city id\n  --aliases             Show all DB aliases\n  --db DB               Create cities database from Geonames file. Can be one of 'xl' ('xlarge'), 'lg' ('large'), 'md'\n                        ('medium'), 'sm' ('small')\n  --db-pop DB_POP       City population minimum.\n  --tz-alias            Search for a time zone alias\n  --fullmoon            Show full moon(s) for given year or month. Can be in the format of: 'next' | 'prev' | YYYY[-MM]\n  -h, --help            Show helpful usage information\n\nUse -v option for details\n```\n\n## Development\n\nRequires Python 3.10+ and [just](https://github.com/casey/just) for convenience.\n\n```console\n$ git clone git@github.com:dakrauth/when.git\n$ cd when\n$ just\n```\n\n> **Note:**\n>\n> _``just`` is a shortcut for ``just --help``_\n\nSet up dev env:\n\n```console\n$ just init\n```\n\nTest, and code coverage:\n\n```console\n$ just test\n$ just cov\n```\n\nOnly run a test matching matching a given substring:\n\n```console\n$ just test -k test_sometest\n```\n\nRun the when command with any arguments:\n\n```console\n$ just when --source poulsbo\n```\n\nOr, start an interactive session:\n\n```console\n$ . ./dev/venv/bin/activate\n$ when --help\n```\n",
    "bugtrack_url": null,
    "license": "MIT License\n        \n        Copyright (c) 2024 David A Krauth\n        \n        Permission is hereby granted, free of charge, to any person obtaining a copy\n        of this software and associated documentation files (the \"Software\"), to deal\n        in the Software without restriction, including without limitation the rights\n        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n        copies of the Software, and to permit persons to whom the Software is\n        furnished to do so, subject to the following conditions:\n        \n        The above copyright notice and this permission notice shall be included in all\n        copies or substantial portions of the Software.\n        \n        THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n        SOFTWARE.\n        ",
    "summary": "Calculate and convert times across time zones and cities of significant population",
    "version": "3.3",
    "project_urls": {
        "Homepage": "https://github.com/dakrauth/when"
    },
    "split_keywords": [
        "time",
        " timezone",
        " timezones"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d10945103212dba5d4a89c9b05fcba736118909a54da4fd330cd388b789bad9c",
                "md5": "c514b893753b5ed8fd7124f2b4b7facc",
                "sha256": "ddd92b11175ae651ade87b3959be7fb6688babe08848ab59a644a58c55d3a05e"
            },
            "downloads": -1,
            "filename": "when-3.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c514b893753b5ed8fd7124f2b4b7facc",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 34443,
            "upload_time": "2025-02-07T18:39:54",
            "upload_time_iso_8601": "2025-02-07T18:39:54.469916Z",
            "url": "https://files.pythonhosted.org/packages/d1/09/45103212dba5d4a89c9b05fcba736118909a54da4fd330cd388b789bad9c/when-3.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "bed73fe60c5ad35b4cd3773089aa5bdb60cfbf6d76394359a7f1bcdb9d55d2ce",
                "md5": "a574b7e11314791df8a76a83228ec005",
                "sha256": "5324ce0593a1c7287ae18aab2cf3c91bae91b05632456203f96858c9ab2023c1"
            },
            "downloads": -1,
            "filename": "when-3.3.tar.gz",
            "has_sig": false,
            "md5_digest": "a574b7e11314791df8a76a83228ec005",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 45426,
            "upload_time": "2025-02-07T18:39:55",
            "upload_time_iso_8601": "2025-02-07T18:39:55.935334Z",
            "url": "https://files.pythonhosted.org/packages/be/d7/3fe60c5ad35b4cd3773089aa5bdb60cfbf6d76394359a7f1bcdb9d55d2ce/when-3.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-02-07 18:39:55",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "dakrauth",
    "github_project": "when",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "tox": true,
    "lcname": "when"
}
        
Elapsed time: 0.47165s