Skip to main content
Version: 11.2

$.udb.ioFormat

note

This article is about the ioFormat objrct of the udb object. It is implemented in usoft.module.data.ioformat.js, and is used from many places throughout the UDB layer to format and parse column values.

$.udb.ioFormat

Handles all formatting and parsing of values between their raw (conceptual) representation and the formatted string that a user sees, or types into an input field. Formatting is driven by an ioFormat mask string — the same kind of format mask configured on a Definer column, and returned by Cols.ioFormat() — combined with the value's value type ('String', 'Integer', 'Real', 'Date', 'DateTime' or 'Binary').

You will not normally call $.udb.ioFormat directly from everyday page scripting; column display and input formatting already goes through it automatically. It is documented here because it is also useful directly, for example to format or validate a value yourself, and because it is what the Date extension functions .dateFormat() and Date.parseDate() use internally.

Syntax

$.udb.ioFormat.functionName( ...args )

Functions

FunctionExplanation
.format(*value*, *ioFormat*, *valueType*, *search*)Formats a raw value into a display string, according to ioFormat and valueType.
.parse(*formatted*, *ioFormat*, *valueType*, *search*, *alt*)Parses a formatted display string back into a raw value, according to ioFormat and valueType.
.validate(*value*, *ioFormat*, *valueType*, *search*, *alt*)Returns whether value is a valid, formatted value for ioFormat and valueType: whether it can be parsed, and the parsed result formatted again, without error.
.canFormat(*value*, *ioFormat*, *valueType*, *search*, *alt*)Returns whether a raw value can be formatted with ioFormat and remains stable under a further format/parse round-trip (for 'Real', comparing numerically rather than textually).
.getLength(*ioFormat*)Returns the display length, in characters, implied by ioFormat, or -1 if that length is variable (e.g. ioFormat contains $$SHORTDATE$$ or $$LONGDATE$$).
.expand(*ioFormat*)Expands the (n) repeat-count shorthand (see below) in ioFormat into its fully written-out form.
.getTypeOfValue(*valueType*)Maps a Definer value type ('String', 'Integer', 'Real', 'Date', 'DateTime', 'Binary') to the internal category ('string', 'number', 'date', or undefined for 'Binary') that the functions above operate on.
.toConceptual(*value*, *ioFormat*, *valueType*, *search*, *alt*)Converts a display value into USoft's internal, format-independent "conceptual" representation — the canonical fixed format used internally, regardless of ioFormat.
.getUnparsedValue(*value*, *ioFormat*, *valueType*)Similar to .parse(), but skipped entirely while the page is being previewed in Web Designer (IsPreview), and, for numbers, only strips group separators rather than fully parsing.
.getLanguageIoFormat(*ioFormat*, *valueType*)For a number ioFormat, replaces its language-neutral ./, placeholders with the current language's actual decimal/group separator characters (see below). Returns ioFormat unchanged for other value types.
note

$.udb.ioFormat.string, $.udb.ioFormat.number and $.udb.ioFormat.date additionally expose the lower-level, type-specific .format(value, ioFormat)/.parse(value, ioFormat) pair that the functions above dispatch to internally, in case you already know a value's type and want to skip that dispatch. Prefer the valueType-based functions above in everyday code.

warning

.validate() only checks that a value can be parsed and then formatted again without error — it does not check that doing so reproduces the original string. For dates, this means a calendar-invalid value such as 31-02-2026 (February has no 31st) still validates successfully: JavaScript's native Date silently rolls it over to the 3rd of March, no exception is thrown, and .validate() never compares against the original string to notice. If you need to catch this kind of input error, parse the value and format it back yourself, and compare that against the original input:

let parsed = $.udb.ioFormat.parse(input, ioFormat, 'Date');
let isReallyValid = $.udb.ioFormat.format(parsed, ioFormat, 'Date') === input;

The ioFormat mask language

An ioFormat mask is built up out of tokens, each standing for a part of a date, or a placeholder for a digit or character. Tokens are modeled after Oracle SQL date/number format models, and are matched case-sensitively, longest-match first (e.g. YYYY is matched as a whole before falling back to YYY, YY, or Y).

Date tokens

TokenMeaning
CCYYYear, 4 digits.
YYYYYear, 4 digits.
SYYYYYear, 4 digits, signed (for years before year 0).
YYYLast 3 digits of the year.
YYLast 2 digits of the year.
YLast digit of the year.
RRYear, 2 digits, with automatic century roll-over: values greater than 49 are taken to be in the previous century.
CCCentury, 2 digits.
SCCCentury, 2 digits, signed.
QQuarter of the year, 1 digit (1-4).
MMMonth, 2 digits.
MONTHFull month name.
MONAbbreviated (3-letter) month name.
WWISO week number of the year, 2 digits.
WWeek of the month, 1 digit (1-5).
DDDDay of the year, 3 digits.
DDDay of the month, 2 digits.
DAYFull weekday name.
DYAbbreviated (3-letter) weekday name.
DDay of the week, 1 digit.
HH24Hour, 2 digits, 24-hour clock.
HH12 / HHHour, 2 digits, 12-hour clock.
MIMinutes, 2 digits.
SSSeconds, 2 digits.
AM / PMDisplays AM or PM as appropriate. Either token may be used; both behave identically.

Number and string tokens

TokenMeaning
9A digit; unfilled positions are zero-padded.
ZA digit; unfilled positions produce no character at all, rather than being zero-padded.
A / XA single alphanumeric character (string masks only). Both tokens behave identically.
BA blank (space) filler.
+Sign placeholder: + for positive, - for negative.
-Sign placeholder: nothing for positive, - for negative.
$ / £ / Currency symbol.
.Decimal separator — always write . in the mask itself; see the note below.
,Group (thousands) separator — always write , in the mask itself; see the note below.
/, :, ;Literal separator characters.
note

Always write . for the decimal separator and , for the group separator directly in the ioFormat mask, regardless of what characters the current language actually uses for these. $.udb.ioFormat.getLanguageIoFormat() (and formatting/parsing in general) automatically substitutes the current language's real decimal and group separator characters wherever . and , appear in the mask.

warning

9 and Z are the reverse of what you may expect from Oracle format masks: here, 9 is the token that zero-pads, and Z is the one that leaves blanks. Double-check which one you want when porting a format mask from elsewhere.

Literal text and repeated tokens

Any part of an ioFormat mask enclosed in double quotes is copied through literally, instead of being interpreted as tokens. This is how USoft's own internal, fixed "conceptual" date format embeds a literal T between the date and time parts, ISO-8601 style:

'YYYY-MM-DD"T"HH24:MI:SS'

A token or literal character immediately followed by (n) is repeated to a total of n occurrences. For example, in a string or number mask, 9(5) is equivalent to writing 99999 out in full, and .expand() is the function that performs this expansion.

The search parameter

.format() and .parse() both accept an optional search flag. When true, instead of formatting/parsing a plain value, the input is treated as a search/filter expression, which may combine values with:

  • = : prefix for an explicit equality condition.
  • <, >, <=, >=, <> : comparison operators.
  • ! : negation.
  • | : OR — combines multiple conditions, each individually formatted/parsed.
  • & : AND — combines multiple conditions, each individually formatted/parsed.
  • %, _ : SQL-style wildcards, passed through unformatted.
  • NULL (any case) : passed through as-is.

This is what allows a search field bound to a Date or Real column to accept expressions like >01-01-2026 or >=10&<=20, formatting or parsing each side of the expression individually while leaving the operators intact.

Examples

// format a raw conceptual date into a display string
$.udb.ioFormat.format('2026-08-10T00:00:00', 'DD-MM-YYYY', 'Date');
// '10-08-2026'

// parse a display string back into a raw conceptual date
$.udb.ioFormat.parse('10-08-2026', 'DD-MM-YYYY', 'Date');
// '2026-08-10T00:00:00'

// zero-padded vs unpadded digit placeholders
$.udb.ioFormat.format('7', '999', 'Integer'); // '007'
$.udb.ioFormat.format('7', 'ZZZ', 'Integer'); // '7'

// validate a typed value against a format before committing it
$.udb.ioFormat.validate('10-08-2026', 'DD-MM-YYYY', 'Date'); // true
$.udb.ioFormat.validate('not-a-date', 'DD-MM-YYYY', 'Date'); // false

// format a search/filter expression
$.udb.ioFormat.format('>01-01-2026&<01-06-2026', 'DD-MM-YYYY', 'Date', true);