Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 87 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,20 @@ It works the other way too. Someone in a different timezone drops a timestamp in
chat ("it broke at 14:35"), and you just paste it in and convert it into your
own timezone without a second thought.

When an incident spans a team spread across three continents, you can pass
`--to` more than once and get every one of those zones in a single block - handy
for a timeline in the postmortem, or for working out whether paging Bengaluru at
that hour was reasonable.

And because your day probably revolves around a handful of the same zones, you
can wrap `tzc` in a couple of **shell aliases** so a conversion is one short
word away.

`tzc` reads basically any timestamp you are likely to copy (SQL, ISO-8601 /
Kubernetes, syslog, Apache, `date` output, Unix epoch in seconds through
nanoseconds, and even plain-English "31 days, 4 hours, 25 minutes ago"), lets
you pick the target zone with an `fzf` fuzzy search, and prints the result in a
clean Catppuccin-colored block.
you pick one or more target zones with an `fzf` fuzzy search, and prints the
results in a clean Catppuccin-colored block.

---

Expand All @@ -50,12 +55,15 @@ clean Catppuccin-colored block.
nanoseconds, detected automatically
- **Human-readable relative input** - type `31 days, 4 hours, 25 minutes ago` or
`in 3 hours` and it resolves against now
- **Many zones at once** - repeat `--to` (or give it a comma-separated list) to
convert one timestamp into every zone your team sits in, in one block
- **fzf timezone picker** - fuzzy-search the full IANA list, annotated with each
zone's abbreviation and current UTC offset (search `IST` or `-8h`)
zone's abbreviation and current UTC offset (search `IST` or `-8h`), and press
`TAB` to select several zones at once
- **Tells you how long ago** - every result includes a friendly relative time
like `31 days, 4 hours ago`
- **Shell-alias friendly** - pass `--to` to skip the picker and bake your common
conversions into one-word aliases
conversions - including whole-team, multi-zone ones - into one-word aliases
- **Readable output** - Catppuccin Mocha colors that auto-disable when piped or
when `NO_COLOR` is set
- **Single file, standard library only** - the one optional extra is `fzf`, and
Expand All @@ -67,8 +75,9 @@ clean Catppuccin-colored block.

- **Python 3.9+** (uses the standard-library `zoneinfo` module)
- **[fzf](https://github.com/junegunn/fzf)** for the interactive timezone
picker. Optional: if `fzf` is not installed, or you pass `--to`, `tzc` falls
back to a plain text prompt or that value.
picker, including `TAB` multi-select. Optional: if `fzf` is not installed, or
you pass `--to`, `tzc` falls back to a plain text prompt (which accepts a
comma-separated list of zones) or those values.
- **IANA tz database** - present on macOS and most Linux systems. On a minimal
install you may need it from PyPI: `pip install tzdata`.

Expand Down Expand Up @@ -109,6 +118,12 @@ tzc "2026-07-24T14:35:18Z"
# Skip the picker by naming the target zone
tzc "2026-07-24 14:35:18" --to America/New_York

# Repeat --to for several zones at once - one line of output per zone
tzc "2026-07-24T14:35:18Z" --to America/New_York --to Europe/London --to Asia/Kolkata

# Same thing, comma-separated (mix and match if you like)
tzc "2026-07-24T14:35:18Z" --to America/New_York,Europe/London,Asia/Kolkata

# A teammate pasted their local time in chat; convert it to yours
tzc "Fri Jul 24 07:19:59 PDT 2026" --to Europe/London

Expand All @@ -133,6 +148,39 @@ tzc "in 3 hours" --to Asia/Kolkata
tzc "2026-07-24T14:35:18Z" --to UTC --no-color
```

### One timestamp, every zone your team is in

`--to` is repeatable, and each one also accepts a comma-separated list, so these
are all equivalent:

```bash
tzc 1784903718 --to America/Los_Angeles --to Europe/London --to Asia/Tokyo
tzc 1784903718 --to America/Los_Angeles,Europe/London,Asia/Tokyo
tzc 1784903718 --to America/Los_Angeles,Europe/London --to Asia/Tokyo
```

You get one line per zone, in the order you listed them, with everything else in
the block unchanged:

```
Timezone Conversion
---------------------
Input string : 2026-07-24T14:35:18Z
-> parsed with explicit timezone
Entered time : 2026-07-24 14:35:18 UTC (+0000)
Converted to : 2026-07-24 07:35:18 PDT (-0700) [America/Los_Angeles]
2026-07-24 10:35:18 EDT (-0400) [America/New_York]
2026-07-24 15:35:18 BST (+0100) [Europe/London]
2026-07-24 20:05:18 IST (+0530) [Asia/Kolkata]
2026-07-24 23:35:18 JST (+0900) [Asia/Tokyo]
UTC : 2026-07-24 14:35:18 UTC (+0000)
Epoch seconds: 1784903718
Relative : 46 days, 3 hours, 50 minutes ago
```

Duplicate zones are dropped, so a comma list that overlaps with a flag (or with
an alias you wrapped it in) will not print the same zone twice.

### The fzf picker

Run `tzc` with no `--to` and you get a fuzzy-searchable list of every IANA zone,
Expand All @@ -147,6 +195,9 @@ Europe/London GMT/BST +1h
Search by zone name (`tokyo`), by abbreviation (`IST` surfaces India, Ireland,
and Israel so you can pick the right one), or even by offset (`-8h`).

The picker is multi-select: press `TAB` to mark a zone (`Shift-TAB` to unmark),
mark as many as you want, then `Enter` to convert to all of them at once.

---

## Shell aliases
Expand Down Expand Up @@ -178,6 +229,23 @@ alias tzsyd='tzc --to Australia/Sydney' # SYD Sydney
# usage: tzsfo "2026-07-24T14:35:18Z"
```

Since `--to` is repeatable, an alias can cover a whole group of people at once -
your on-call rotation, the team you hand off to, or everyone who will read the
incident timeline:

```bash
# the whole team, in one shot
alias tzteam='tzc --to America/Los_Angeles --to America/New_York --to Europe/London --to Asia/Kolkata'

# follow-the-sun on-call handoff: who is awake right now?
alias tzoncall='tzc --to America/Los_Angeles,Europe/Berlin,Asia/Singapore'

# just the two ends of your handoff window
alias tzhandoff='tzc --to America/New_York,Asia/Kolkata'

# usage: tzteam "2026-07-24T14:35:18Z"
```

Prefer functions so you can convert whatever is on your clipboard in one shot:

```bash
Expand All @@ -186,9 +254,13 @@ tznow() { tzc "$(pbpaste)" --to America/New_York; }

# Linux with xclip - convert the clipboard to your local zone
tzhere() { tzc "$(xclip -o -selection clipboard)"; }

# clipboard -> your zone plus everyone you are working the incident with
tzall() { tzc "$(pbpaste)" --to America/Los_Angeles,Europe/London,Asia/Kolkata; }
```

Now copy a timestamp out of a log, run `tznow`, and you are done.
Now copy a timestamp out of a log, run `tznow` (or `tzall` when you need to
share it), and you are done.

---

Expand Down Expand Up @@ -217,14 +289,15 @@ timezone unless you pass `--from`.

## Options

| Flag | Description |
| ------------- | -------------------------------------------------------------- |
| `--to ZONE` | Target timezone; skips the fzf picker (e.g. `--to Asia/Tokyo`) |
| `--from ZONE` | Timezone to assume for naive inputs (default: your local zone) |
| `--no-color` | Disable the Catppuccin colored output |
| Flag | Description |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `--to ZONE` | Target timezone; skips the fzf picker (e.g. `--to Asia/Tokyo`). Repeatable, and accepts a comma-separated list, to convert to several zones at once |
| `--from ZONE` | Timezone to assume for naive inputs (default: your local zone) |
| `--no-color` | Disable the Catppuccin colored output |

Output includes the parsed input, the entered time, the converted time, the UTC
equivalent, the Unix epoch, and a friendly relative time.
Output includes the parsed input, the entered time, the converted time (one line
per `--to` zone), the UTC equivalent, the Unix epoch, and a friendly relative
time.

---

Expand Down
Loading
Loading