Guides

Formatting

Display numbers, dates, calendar dates, coordinates and unit labels from .well data without floating-point noise or time zone shifts, using the display helpers of @welldot/utils.

These helpers turn stored values into text for screens, PDFs and tables. They are framework-free and are shared by the welldot.org editor and @welldot/pdf. Anything that needs translated words takes them as plain strings, so you keep your own message catalog.

Numbers

Floating-point arithmetic produces values like 39.99998784. formatNumber bounds the decimals so that noise never reaches the reader:

import { formatNumber } from '@welldot/utils';

formatNumber(39.99998784, { fractionDigits: 2, suffix: 'm' }); // '40.00 m'
formatNumber(1234.5, { locale: 'pt-BR', maximumFractionDigits: 1 }); // '1.234,5'
formatNumber(undefined); // '—'

Options: fractionDigits (fixed), minimumFractionDigits, maximumFractionDigits, suffix, locale (a BCP 47 tag, default en-US) and fallback (default —, shown for null, undefined and NaN). An absent value shows as a dash, never as 0, following the format's "absent means unknown" rule.

Dates

The format has two kinds of temporal values (datetime conventions): calendar dates (YYYY-MM-DD, for construction and permits) and instants (RFC 3339 with an offset, for everything measured). Handle them differently:

import {
  formatCalendarDate,
  formatDate,
  fromCalendarDate,
  toCalendarDate,
} from '@welldot/utils';

formatCalendarDate('2025-03-01'); // '01/03/2025', no time zone shift
formatCalendarDate('2025-03-01', 'yyyy-MM-dd'); // any date-fns pattern

formatDate(new Date('2025-03-01T10:00:00Z')); // 'dd/MM/yyyy HH:mm' in the runtime's time zone

toCalendarDate(new Date(2025, 2, 1)); // '2025-03-01', from a local Date, never through UTC
fromCalendarDate('2025-03-01'); // a local Date, or null when malformed
Never pass a calendar date to new Date('2025-03-01'): JavaScript reads it as UTC midnight, which is the previous day in the Americas. Use fromCalendarDate and formatCalendarDate.

For the local date of an instant at the well site, use instantLocalDate(instant, timeZone) with the zone from getWellTimeZone(well) (Permits).

Coordinates

import { formatCoord, parseToDd } from '@welldot/utils';

formatCoord(-1.4558, 'DMS', true); // `1°27'20.88"S` (true = latitude)
formatCoord(-1.4558, 'DD', true); // '-1.455800'
parseToDd(`1°27'20.88"S`); // -1.4558, from DD or DMS text; NaN when unreadable

clampLat and clampLng keep typed values in range. Projected coordinates are not handled here; the file stores latitude and longitude only (CRS scope).

Unit labels

FunctionReturns
resolveFlowUnitLabel(unit)m³/h, L/s, gpm for the storage tokens m3/h, L/s, gpm.
resolveVolumeUnitLabel(unit)m³, L, ft³, gal.
resolveDiameterUnitLabel(unit, locale)mm, or " in Portuguese and in. in English for inches.

Convert the values themselves with the unit conversion helpers of @welldot/core.

Records

  • formatMeterLabel(meter, { locale, untypedLabel, dateFormat? }): Electromagnetic · S/N 123 · 01/02/2024.
  • permitLabel(permit, fallback?): the authority and identifier of a permit.
  • formatWaterQualityResult(result, labels): < 0.001, 0.004 (est.), the not-detected, present or absent label, or the text (Water quality).