Script a Timezone Lookup with tzselect

Piping answers into tzselect lets a script capture a validated IANA identifier such as Europe/London without ever touching the machine's own timezone. It asks questions, prints a choice, and exits: no configuration file, no root, nothing to undo.

This guide uses tzselect from glibc 2.39, supplied here by libc-bin 2.39-0ubuntu8.9. The installed timezone data is from tzdata 2026c-0ubuntu0.24.04.1. Allow five minutes for a normal selection, or ten minutes if you are checking coordinates and the available matches.

You need a shell and a clear idea of the location whose civil time you want. No command in this guide needs sudo. The examples are read-only apart from setting shell variables in the current shell.

1. Check the installed command

Confirm which executable will run and record its version. These are ordinary, read-only commands:

$ command -v tzselect
/usr/bin/tzselect
$ tzselect --version
tzselect (Ubuntu GLIBC 2.39-0ubuntu8.9) 2.39
$ dpkg-query -W -f='${Package} ${Version}\n' tzdata
tzdata 2026c-0ubuntu0.24.04.1

Checkpoint: if command -v finds a copy outside the expected system path, inspect that copy before trusting its prompts or data. The manpage documents TZDIR, which defaults to /usr/share/zoneinfo, and AWK, which defaults to awk.

2. Choose a timezone by region

Run tzselect with no arguments. It first asks for a continent or ocean, then narrows the list by country and city. The final answer is printed on standard output:

$ tzselect
Please identify a location so that time zone rules can be set correctly.
Please select a continent, ocean, "coord", or "TZ".
#? 7
Please select a country whose clocks agree with yours.
#? 8
The following information has been given:

	Britain (UK)

Therefore TZ='Europe/London' will be used.
Is the above information OK?
1) Yes
2) No
#? 1
Europe/London

Menu numbers vary with the installed timezone data. Do not copy a number from this transcript without reading the menu in front of you: the confirmation question is a useful pause, so check the proposed TZ value before accepting it.

If the location is not represented by one city, choose the timezone whose rules match the civil time you need. Country borders and political preferences do not always map cleanly to one timezone; tzselect reports a practical match, it does not decide which political preference is correct.

3. Use coordinates when the menu is awkward

With -c, give an ISO 6709 latitude immediately followed by longitude. In the default C locale, decimal degrees are straightforward:

$ printf '1\n' | LC_ALL=C tzselect -c +51.5074-000.1278
Please select one of the following timezones, echo listed roughly in increasing order of distance from +51.5074-000.1278.
 1) France, Monaco
 2) Belgium, Luxembourg, Netherlands
 3) Ireland
...
Therefore TZ='Europe/Paris' will be used.
Is the above information OK?
1) Yes
2) No
#?

The example feeds only the first selection, so the command reaches the confirmation prompt and then sees end of input. For an unattended test, provide both answers and capture the final line:

$ printf '1\n1\n' | LC_ALL=C tzselect -c +51.5074-000.1278 | tail -n 1
Europe/Paris

That is intentionally not a claim that Paris is the correct choice for every point near London. Coordinate mode ranks timezones by the locations used in its data tables, and the first result may not match your preferred local rule. Read the list and choose the appropriate item.

Use -n to reduce or expand the number of displayed matches:

$ printf '1\n1\n' | LC_ALL=C tzselect -c +51.5074-000.1278 -n 3 | tail -n 1
Europe/Paris

The default limit is 10. Keep the coordinate in a documented form: the manpage says malformed coordinates have unspecified behaviour, so do not use this option to validate arbitrary user input.

4. Capture and verify the result

For a script or a temporary shell session, capture the final line only after you have checked the interactive choice. This example makes a fresh selection and stores the printed timezone:

$ TZ_NAME=$(printf '1\n1\n' | LC_ALL=C tzselect -c +51.5074-000.1278 | tail -n 1)
$ printf 'selected TZ: %s\n' "$TZ_NAME"
selected TZ: Europe/Paris
$ TZ="$TZ_NAME" date '+%Y-%m-%d %H:%M %Z %z'
2026-09-27 16:29 CEST +0200

The date and abbreviation depend on the current clock and the selected zone. The useful checks are that the variable contains a named zone and that a program using TZ shows a plausible offset. A successful tzselect run exits with status zero; a failed or cancelled run exits non-zero.

Warning: do not silently pipe arbitrary interactive output into a variable in production. A changed menu, a rejected answer or an interrupted run can leave diagnostics in the captured text. For a human workflow, run the command normally and copy its final line; for automation, validate the exit status and the resulting name before using it.

5. Understand what has and has not changed

Setting TZ for one command affects that command and its children only:

$ TZ=Europe/London date '+%Y-%m-%d %H:%M %Z %z'
2026-09-27 15:29 BST +0100
$ date '+%Y-%m-%d %H:%M %Z %z'
2026-09-27 14:29 UTC +0000

The second command does not inherit the temporary assignment. To keep the setting in the current interactive shell, assign it explicitly:

$ export TZ=Europe/London
$ date '+%Y-%m-%d %H:%M %Z %z'
2026-09-27 15:29 BST +0100
$ unset TZ
$ date '+%Y-%m-%d %H:%M %Z %z'
2026-09-27 14:29 UTC +0000

Recovery: unset TZ is the undo operation for that shell export. It does not alter the host's timezone configuration. If a service, container or login manager needs a persistent timezone, use that system's documented configuration workflow separately; do not assume that running tzselect has configured any of them.

Common traps

Done means