GrDuration

  • chrono
  • chrono
  • API · 8 props
import { GrDuration } from '@feugene/granularity-chrono/components/GrDuration'

Overview

When to take it

  • how long it took — the duration of a call, the time of a build, the downtime of equipment: “2 h 30 min” reads faster than “9000”;
  • how long it has been running right now — pass the moment of the start as a single date, and the label becomes live: the timer is shared across the whole application and is removed on a hidden tab;
  • the interval between two moments — a pair of dates is computed by itself, and there is no need to subtract milliseconds by hand;
  • the value travels into the markup — datetime is filled with the exact length in ISO 8601, even when the text has been shortened to two units.

When to take something else

NeedTake
Show how long ago it wasGrRelativeTime
Choose a moment rather than show a lengthGrDatePicker / GrTimePicker
Enter a duration rather than show itGrNumberInput
Show the share of what has elapsed out of the wholeGrProgressBar

Examples 3 each with a live demo and its code

  • How long the pipeline took

    Each run is a pair of Dates as the CI API returns them — a measured interval, no subtracting milliseconds by hand. max-units="2" with width="narrow" reads «23m 29s» and drops the rest rather than rounding up. The default slot keeps the text and draws a bar against the slowest run, while the <time> around it still carries the exact length in 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
  • A call that is still going

    One date is the moment the call started: with live the label counts up to «now» on a shared timer, ticking every second only because seconds are shown. Ending the call hands over a pair of dates — the same component, a fixed length. The history below is numbers in seconds, kept coarse with 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
  • The phases of an outage

    An outage longer than a day is still counted in hours by the people who lived through it: largest-unit="hour" keeps «27 hr, 15 min» instead of «1 day, 3 hr». The notice for customers is prose, so units get full names with width="long", and each status page, English and German, names its language with locale whatever the language of the admin around it. There the start date is measured against base rather than the clock, so the text is the same on the server and in the browser.

    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 generated from the package · cannot drift

Props

PropTypedefaultDescription
localestring | undefinedundefinedDisplay locale. Not set — from the application's i18n adapter.
valuenumber | Date | readonly [Date, Date] | null | undefinedundefinedWhat to measure. Three forms, each distinguishable by type: - **a number** — seconds; - **a pair of dates** — the span between them; - **a single date** — from it up to "now"; such a label is live and ticks.
baseDate | undefinedundefinedWhat to compare against instead of "now" — for the single-date form. When set, the clock is not read at all: no timer, no divergence between server and client rendering. The same makes tests and snapshots reproducible.
liveboolean | undefinedundefinedUpdate live. The component picks the tick itself from the smallest unit shown.
maxUnitsnumber | undefinedundefinedHow many units to show in a row: `2` gives "2 h 30 min".
largestUnitDurationUnit | undefinedundefinedDo not split above this unit: the remainder accumulates in it.
smallestUnitDurationUnit | undefinedundefinedDo not go below this one.
widthNameWidth | undefinedundefinedLength of the unit names: "2 hours 30 minutes" versus "2 hr 30 min".

Slots

SlotTypeDescription
default{ text: string; datetime: string; seconds: number; }Custom markup instead of the text: the same values the component renders itself.

Types

Every exported type of the subpath, grouped by the file it lives in. Names, generics and bodies come from the package’s declaration files and cannot drift.

Import
import type { GrDurationConfigurableProps, GrDurationProps } from '@feugene/granularity-chrono/components/GrDuration'

Filedist/types/components/GrDuration/config.d.ts

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

Filedist/types/components/GrDuration/defaults.d.ts

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

Filedist/types/components/GrDuration/safelist.d.ts

grDurationSafelistconst
const grDurationSafelist: string[];

Filedist/types/components/GrDuration/GrDuration.vue.d.ts

GrDurationPropsinterface
interface GrDurationProps {
    value?: number | Date | readonly [Date, Date] | null;
    base?: Date;
    live?: boolean;
    maxUnits?: number;
    largestUnit?: DurationUnit;
    smallestUnit?: DurationUnit;
    width?: NameWidth;
    locale?: string;
}

Usage from the library prose

There are four units, and there will be nothing larger

Days, hours, minutes, seconds. Months and years are deliberately not here: they are calendar ones — of different lengths in February and in July — and they cannot be derived from a number of seconds without lying. A gap that really is measured by the calendar is shown by GrRelativeTime, and computed by differenceInMonths.

A ceiling rather than a quota

maxUnits limits the number of units from above and adds nothing: exactly two hours is “2 h” rather than “2 h 0 min”. The smaller part is discarded rather than rounded — “2 h 59 min 30 s” stays “2 h 59 min”. Rounding would raise the display above the time that really has elapsed, and this value is usually used to measure precisely that.

Zero is the only exception to the discarding: “0 s” is printed, because an empty string reads as “there is no data”, and a zero means something else.

A live label belongs only to the form with a single date

A number and a pair of dates set the length as a whole, and there is nothing in them to tick. The moment of the start is another matter: until “now” the time keeps running, and the label recomputes itself. The tick is chosen by the smallest unit shown, so a label in hours does not wake the tab every second.

The live display is derived from the clock, which means the server render and the client one will diverge. The component marks that with data-allow-mismatch, and the mark is removed not by a flag but by data: pass base and the render becomes deterministic.

Limits

There is no countdown here: “2 h 30 min left” is the same length, but a deadline, a zero and the transition into negative values belong to a scenario rather than to a label. Compute the remainder yourself and pass it as a number.