Форматы времени

Работа со временем в пользовательских интерфейсах требует точности, локализации и доступности. В веб-приложениях время может отображаться в различных форматах: 12-часовом и 24-часовом, с указанием секунд, с использованием локализованных обозначений периода суток, а также с различными правилами форматирования в зависимости от региона пользователя.

Библиотека React Aria предоставляет инструменты для создания доступных и локализованных компонентов работы со временем. В основе этих инструментов лежит интеграция с библиотеками React Stately и @internationalized/date, которые обеспечивают корректное представление временных значений, работу с часовыми поясами и автоматическое форматирование на основе локали.


Модель представления времени

В React Aria временные значения представляются не обычными объектами JavaScript Date, а специализированными структурами из пакета @internationalized/date. Основным типом является Time.

import {Time} from '@internationalized/date';

let time = new Time(14, 30);

Объект Time содержит:

  • часы
  • минуты
  • секунды
  • миллисекунды

Такой подход позволяет:

  • избегать проблем с часовыми поясами
  • точно управлять частями времени
  • корректно обрабатывать локализацию

Структура объекта:

Time {
  hour
  minute
  second
  millisecond
}

Каждая часть времени может быть изменена независимо.


Использование TimeField

Компонент TimeField предназначен для ввода времени. Он автоматически разбивает время на сегменты (часы, минуты, секунды) и обеспечивает корректную навигацию между ними.

Пример использования:

import {useTimeField} from 'react-aria';
import {useTimeFieldState} from 'react-stately';
import {Time} from '@internationalized/date';

function TimeField(props) {
  let state = useTimeFieldState({
    ...props,
    defaultValue: new Time(9, 30)
  });

  let ref = React.useRef();
  let {labelProps, fieldProps} = useTimeField(props, state, ref);

  return (
    <div>
      <label {...labelProps}>Время</label>
      <div {...fieldProps} ref={ref}>
        {state.segments.map(segment => (
          <span key={segment.type}>{segment.text}</span>
        ))}
      </div>
    </div>
  );
}

TimeField автоматически учитывает:

  • локальный формат времени
  • направление текста
  • доступность для экранных читалок
  • клавиатурную навигацию

Сегментированное представление времени

React Aria разбивает время на сегменты. Каждый сегмент представляет часть временного значения.

Типы сегментов:

Сегмент Описание
hour часы
minute минуты
second секунды
dayPeriod AM / PM
literal разделители

Пример отображения времени:

14 : 30

Разбивка сегментов:

hour → "14"
literal → ":"
minute → "30"

Сегментированная модель обеспечивает:

  • точное редактирование отдельных частей
  • удобную клавиатурную навигацию
  • улучшенную доступность

Локализация форматов времени

React Aria автоматически использует Intl API браузера для определения формата времени в зависимости от локали.

Примеры:

США

2:30 PM

Германия

14:30

Япония

14:30

Формат определяется через locale.

useTimeFieldState({
  locale: 'en-US'
})

Изменение локали автоматически меняет:

  • порядок сегментов
  • использование AM/PM
  • разделители
  • формат отображения

12-часовой и 24-часовой формат

Формат времени определяется параметром hourCycle.

Возможные значения:

Значение Формат
h11 0–11
h12 1–12
h23 0–23
h24 1–24

Пример установки 24-часового формата:

useTimeFieldState({
  hourCycle: 24
})

В результате:

14:30

Для 12-часового формата:

hourCycle: 12

Отображение:

2:30 PM

Форматирование времени

Для преобразования временного значения в строку используется DateFormatter.

import {DateFormatter} from '@internationalized/date';

let formatter = new DateFormatter('ru-RU', {
  hour: 'numeric',
  minute: '2-digit'
});

formatter.format(new Date());

Опции форматирования:

Опция Назначение
hour формат часов
minute формат минут
second секунды
hour12 использование AM/PM

Пример с секундами:

let formatter = new DateFormatter('ru-RU', {
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit'
});

Результат:

14:30:05

Управление шагом времени

Компонент может ограничивать шаг изменения времени.

Параметр:

granularity

Возможные значения:

Значение Описание
hour изменение часов
minute минуты
second секунды

Пример:

useTimeFieldState({
  granularity: 'minute'
})

Это означает, что пользователь может редактировать:

часы + минуты

Для секунд:

granularity: 'second'

Отображение:

14:30:15

Ограничение диапазона времени

React Aria позволяет задавать минимальное и максимальное время.

Параметры:

minValue
maxValue

Пример:

import {Time} from '@internationalized/date';

useTimeFieldState({
  minValue: new Time(9, 0),
  maxValue: new Time(18, 0)
});

Разрешённый диапазон:

09:00 — 18:00

Попытка выйти за пределы диапазона будет предотвращена.


Работа с секундными форматами

Для отображения секунд необходимо указать granularity: "second".

useTimeFieldState({
  granularity: "second"
})

Формат отображения:

14:30:45

Сегменты:

hour
minute
second

Это часто используется для:

  • таймеров
  • систем логирования
  • медиа-плееров
  • задач синхронизации

Обработка изменения времени

React Aria использует контролируемую модель компонентов.

Пример:

function Example() {
  let [value, setValue] = React.useState(new Time(10, 0));

  return (
    <TimeField
      value={value}
      onCha nge={setValue}
    />
  );
}

При изменении сегмента вызывается:

onChange(newTime)

Это позволяет:

  • синхронизировать состояние
  • сохранять значения
  • валидировать ввод

Навигация с клавиатуры

Компонент TimeField полностью поддерживает клавиатурную навигацию.

Основные действия:

Клавиша Действие
Tab переход между сегментами
ArrowUp увеличение значения
ArrowDown уменьшение
ArrowLeft предыдущий сегмент
ArrowRight следующий сегмент

При достижении максимального значения происходит циклический переход.

Пример:

23 → 00

Доступность

React Aria реализует требования спецификации ARIA для работы со временем.

Используются:

  • role="spinbutton"
  • aria-valuenow
  • aria-valuemin
  • aria-valuemax

Экранные читалки могут корректно озвучивать сегменты:

Часы: 14
Минуты: 30

Это обеспечивает:

  • поддержку VoiceOver
  • поддержку NVDA
  • поддержку JAWS

Использование TimePicker

TimePicker объединяет поле времени и выпадающий список.

Структура компонента:

TimePicker
 ├─ TimeField
 └─ Popover
     └─ TimeList

Пример:

<TimePicker
  label="Выберите время"
  granularity="minute"
/>

Выпадающий список содержит значения времени с заданным шагом.


Форматы времени и часовые пояса

В React Aria время может использоваться совместно с часовыми поясами через тип ZonedDateTime.

import {ZonedDateTime} from '@internationalized/date';

Это необходимо для:

  • календарей
  • планировщиков
  • международных приложений

Пример значения:

2024-05-10T14:30:00+05:00

Такой формат сохраняет:

  • дату
  • время
  • часовой пояс

Сериализация времени

Для хранения временных значений используется преобразование в строку.

Пример:

time.toString()

Результат:

14:30:00

Для восстановления:

parseTime("14:30:00")

Это позволяет:

  • сохранять время в базе данных
  • передавать через API
  • использовать в URL

Типичные сценарии использования

Форматы времени в React Aria применяются в различных интерфейсах.

Планировщики встреч:

09:00 – начало
10:30 – окончание

Системы бронирования:

Время заезда: 14:00

Медиа-плееры:

00:02:35

Таймеры и секундомеры:

01:25:10

Благодаря сегментированной модели, локализации и поддержке доступности React Aria позволяет реализовывать сложные сценарии работы со временем без необходимости вручную обрабатывать форматирование, навигацию и правила локализации.