GrDuration

  • chrono
  • Дата и время
  • API · 8 props

Берут, когда сколько заняло.

import { GrDuration } from '@feugene/granularity-chrono/components/GrDuration'

Обзор

Когда брать

  • сколько заняло — длительность звонка, время сборки, простой оборудования: «2 ч 30 мин» читается быстрее, чем «9000»;
  • сколько идёт прямо сейчас — передайте момент начала одной датой, и метка станет живой: таймер общий на всё приложение и снимается на скрытой вкладке;
  • промежуток между двумя моментами — пара дат считается сама, вычитать миллисекунды руками не нужно;
  • значение уезжает в разметку — datetime заполняется точной длиной в ISO 8601, даже когда текст сокращён до двух единиц.

Когда взять другое

НужноБерите
Показать, давно ли это былоGrRelativeTime
Выбрать момент, а не показать длинуGrDatePicker / GrTimePicker
Ввести длительность, а не показатьGrNumberInput
Показать долю прошедшего от целогоGrProgressBar

Примеры 3 у каждого — живое демо и его код

  • Сколько шла сборка

    Каждый запуск — пара Date, как её отдаёт API CI: измеренный промежуток, вычитать миллисекунды руками не нужно. max-units="2" с width="narrow" дают «23 мин 29 с», а остаток отбрасывается, а не округляется вверх. Слот по умолчанию сохраняет текст и рисует полосу против самой долгой сборки, а <time> вокруг по-прежнему несёт точную длину в ISO 8601.

    billing-service · pipeline runsToday · the budget for main is 15 minutes
    • #4182 · mainpasseda96c453
    • #4181 · feat/sepa-instantfailed13b92a7
    • #4180 · mainpassed3a71377
    • #4179 · fix/dunning-localepassedca5d8d1
  • Звонок, который ещё идёт

    Одна дата — момент начала звонка: с live метка сама считает до «сейчас» на общем таймере и тикает раз в секунду только потому, что показаны секунды. Завершённый звонок передаёт пару дат — тот же компонент, фиксированная длина. История ниже — числа в секундах, загрублённые smallest-unit="minute".

    AROn call · Ana RibeiroRefund for INV-0419 · +351 912 004 118
    Earlier todayAverage
    • Ben HartleyVAT number on invoices
    • Chloé MoreauCard declined on renewal
    • Diego GarcíaSeats after a downgrade
  • Фазы инцидента

    Инцидент длиннее суток те, кто его пережил, всё равно считают в часах: largest-unit="hour" оставляет «27 ч 15 мин» вместо «1 д 3 ч». Уведомление клиентам — проза, поэтому единицы называются полностью через width="long", а каждая страница статуса, английская и немецкая, называет свой язык через locale, на каком бы языке ни была админка вокруг. Там дата начала меряется от base, а не от часов, и текст на сервере и в браузере совпадает.

    INC-2291 · card and SEPA payments degradedPost-mortem · 28–30 September
    Detectionfrom the first failed charge to the page
    Mitigationcard payments routed to the backup provider
    RecoverySEPA backlog re-sent and reconciled
    Total
    Status page · English Card payments were unavailable for ; no charge was lost.
    Status page · German Kartenzahlungen waren lang nicht verfügbar; keine Zahlung ging verloren.

API порождается из пакета · разойтись не может

Props

PropTypeпо умолчаниюОписание
localestring | undefinedundefinedЛокаль показа. Не задана — из адаптера i18n приложения.
valuenumber | Date | readonly [Date, Date] | null | undefinedundefinedЧто мерить. Три формы, каждая различима по типу: - **число** — секунды; - **пара дат** — промежуток между ними; - **одна дата** — от неё до «сейчас»; такая метка живая и тикает.
baseDate | undefinedundefinedС чем сравнивать вместо «сейчас» — для формы с одной датой. Задан — часы не читаются вовсе: ни таймера, ни расхождения серверного рендера с клиентским. Это же делает воспроизводимыми тесты и снимки.
liveboolean | undefinedundefinedОбновляться живьём. Такт компонент выбирает сам по младшей показанной единице.
maxUnitsnumber | undefinedundefinedСколько единиц показывать подряд: `2` даёт «2 ч 30 мин».
largestUnitDurationUnit | undefinedundefinedКрупнее этой единицы не дробить: остаток копится в ней.
smallestUnitDurationUnit | undefinedundefinedМельче этой не спускаться.
widthNameWidth | undefinedundefinedДлина имён единиц: «2 часа 30 минут» против «2 ч 30 мин».

Слоты

SlotTypeОписание
default{ text: string; datetime: string; seconds: number; }Своя разметка вместо текста: значения те же, что компонент рисует сам.

Типы

Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.

Импорт
import type { GrDurationConfigurableProps, GrDurationProps } from '@feugene/granularity-chrono/components/GrDuration'

Файлdist/types/components/GrDuration/config.d.ts

grDurationConfigconst
const grDurationConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrDuration">;

Файлdist/types/components/GrDuration/defaults.d.ts

GrDurationConfigurablePropsinterface

Пропы GrDuration, настраиваемые глобально через <GrConfigProvider :component-defaults="{ GrDuration: { … } }">. Ровно то, что задают один раз на приложение: подробность и длина имён единиц. Само значение — всегда на месте.

interface GrDurationConfigurableProps {
    width: NameWidth;
    maxUnits: number;
    largestUnit: DurationUnit;
    smallestUnit: DurationUnit;
    live: boolean;
}

Файлdist/types/components/GrDuration/safelist.d.ts

grDurationSafelistconst
const grDurationSafelist: string[];

Файлdist/types/components/GrDuration/GrDuration.vue.d.ts

GrDurationPropsinterface

GrDuration — «2 ч 30 мин»: сколько длилось, а не когда случилось. Имена единиц и склонение числительного знает платформа, поэтому своих строк у компонента нет ни одной — он говорит на всех языках, которые знает движок. Разметка — <time> с машинным datetime в формате ISO 8601: сокращённый текст читает человек, точная длина остаётся машине.

interface GrDurationProps {
    /**
     * Что мерить. Три формы, каждая различима по типу:
     *
     * - **число** — секунды;
     * - **пара дат** — промежуток между ними;
     * - **одна дата** — от неё до «сейчас»; такая метка живая и тикает.
     */
    value?: number | Date | readonly [Date, Date] | null;
    /**
     * С чем сравнивать вместо «сейчас» — для формы с одной датой.
     *
     * Задан — часы не читаются вовсе: ни таймера, ни расхождения серверного
     * рендера с клиентским. Это же делает воспроизводимыми тесты и снимки.
     */
    base?: Date;
    /** Обновляться живьём. Такт компонент выбирает сам по младшей показанной единице. */
    live?: boolean;
    /** Сколько единиц показывать подряд: `2` даёт «2 ч 30 мин». */
    maxUnits?: number;
    /** Крупнее этой единицы не дробить: остаток копится в ней. */
    largestUnit?: DurationUnit;
    /** Мельче этой не спускаться. */
    smallestUnit?: DurationUnit;
    /** Длина имён единиц: «2 часа 30 минут» против «2 ч 30 мин». */
    width?: NameWidth;
    /** Локаль показа. Не задана — из адаптера i18n приложения. */
    locale?: string;
}

Использование из прозы библиотеки

Единиц четыре, и крупнее не будет

Сутки, часы, минуты, секунды. Месяца и года здесь нет намеренно: они календарные — в феврале и в июле разной длины, — и вывести их из числа секунд нельзя, не соврав. Разрыв, который правда меряется календарём, показывает GrRelativeTime, а считает differenceInMonths.

Потолок, а не квота

maxUnits ограничивает число единиц сверху и ничего не добирает: ровно два часа это «2 ч», а не «2 ч 0 мин». Младшее при этом отбрасывается, а не округляется — «2 ч 59 мин 30 с» остаётся «2 ч 59 мин». Округление подняло бы показ выше реально прошедшего времени, а этим значением обычно меряют именно его.

Ноль — единственное исключение из отбрасывания: «0 с» печатается, потому что пустая строка читается как «нет данных», а ноль означает другое.

Живая метка — только у формы с одной датой

Число и пара дат задают длину целиком, тикать в них нечему. Момент начала — другое дело: до «сейчас» время идёт, и метка пересчитывается сама. Такт выбирается по младшей показанной единице, поэтому метка в часах не будит вкладку каждую секунду.

Живой показ выведен из часов, а значит серверный рендер и клиентский разойдутся. Компонент помечает это data-allow-mismatch, и убирается пометка не флагом, а данными: передайте base — рендер станет детерминированным.

Границы

Обратного отсчёта здесь нет: «осталось 2 ч 30 мин» — это та же длина, но дедлайн, ноль и переход в отрицательные значения принадлежат сценарию, а не метке. Считайте остаток сами и передавайте числом.