Skip to content
Devix Open Source

Guide

Locales, clocks and time zones

Twelve hours or twenty-four

Not a flag to set — a fact to look up. en-GB is a 24-hour locale and en-US is a 12-hour one; ar-AE is 12-hour and writes ص and م; de-DE, fr-FR and ja-JP are 24-hour. The picker asks Intl and gets it right without being told.

createTimePicker(input, { locale: 'en-US' });   // 5:30 PM
createTimePicker(input, { locale: 'en-GB' });   // 17:30
createTimePicker(input, { locale: 'ar-AE' });   // ٥:٣٠ م

Override it where a house style demands it:

createTimePicker(input, { locale: 'en-US', hourCycle: 'h23' });   // 17:30 in America

Whatever is shown, the value is "17:30". The two are never the same string and never need to be.

With no locale, the picker reads <html lang> and falls back to the device's.

Digits

Arabic-Indic (٠١٢), Persian (۰۱۲), Devanagari, Bengali and full-width digits are all read as digits, so a person typing on an Arabic keyboard is typing a time. So are ص and م, and the day-period words of whatever locale is in play.

Other clocks

The most-reacted open request on the picker most projects use is for time zones, and the answer has always been "install a date library". It does not need one.

createTimePicker(input, {
  timeZone: 'Asia/Dubai',
  zones: ['Europe/London', 'America/New_York'],
  date: '2026-09-12',
});

Under the list: 14:30 London · 09:30 New York. In January that same 17:30 in Dubai reads 13:30 in London, because the conversion is done at an instant on a date, not with a fixed offset. When a zone is on a different day it says so — 22:30 London (previous day).

date matters only for daylight saving; leave it out and today is used. timeZone defaults to the device's.

Doing it yourself

import { readInZones, instantOf } from '@devix-labs/time-picker/core';

readInZones('2026-09-12', 17 * 3600 + 30 * 60, 'Asia/Dubai', ['Europe/London']);
// [{ zone: 'Europe/London', time: 52200, dayOffset: 0, name: 'GMT+1' }]

new Date(instantOf('2026-09-12', 17 * 3600 + 30 * 60, 'Asia/Dubai')).toISOString();
// the moment 17:30 happens in Dubai that day

An hour a country skips in spring resolves forwards, the way calendars do; an hour it repeats in autumn resolves to the first one.

The core, without the widget

@devix-labs/time-picker/core is 2.7 kB and has no DOM in it — useful on a server, in a worker, or in a validation rule:

import { parseTime, formatTime, toIso, buildSlots, isAvailable } from '@devix-labs/time-picker/core';

toIso(parseTime('5pm'));                               // "17:00"
formatTime(parseTime('17:30'), { locale: 'ar-AE' });   // "٥:٣٠ م"
isAvailable(parseTime('12:30'), { min: 0, max: 86399, disabled: [['12:00', '13:00']] });   // false
buildSlots({ min: parseTime('09:00'), max: parseTime('17:00') }, 30);   // the same rows the panel shows
Updated 15 Sep 2026