UNPKG

@parischap/conversions

Version:

A functional library to replace partially the native Intl API

257 lines 9.71 kB
/** * This module implements a `CVTemplate` (see Template.ts) dedicated to parsing and formatting * dates. It supports many of the available unicode tokens (see * https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table). */ import * as MInspectable from '@parischap/effect-lib/MInspectable'; import * as MMatch from '@parischap/effect-lib/MMatch'; import * as MPipeable from '@parischap/effect-lib/MPipeable'; import * as MString from '@parischap/effect-lib/MString'; import * as MTypes from '@parischap/effect-lib/MTypes'; import * as Array from 'effect/Array'; import * as Either from 'effect/Either'; import {flow} from 'effect/Function'; import * as Function from 'effect/Function'; import * as HashMap from 'effect/HashMap'; import * as Option from 'effect/Option'; import {pipe} from 'effect/Function'; import * as Predicate from 'effect/Predicate'; import * as Record from 'effect/Record'; import * as Struct from 'effect/Struct'; import * as Tuple from 'effect/Tuple'; import * as CVDateTime from './DateTime.js'; import * as CVTemplate from './Template.js'; import * as CVTemplatePart from './TemplatePart.js'; import * as CVTemplatePlaceholder from './TemplatePlaceholder.js'; import * as CVTemplateSeparator from './TemplateSeparator.js'; /** * Module tag * * @category Module markers */ export const moduleTag = '@parischap/conversions/DateTimeFormat/'; const _TypeId = /*#__PURE__*/Symbol.for(moduleTag); /** * Namespace for a TemplatePart * * @category Models */ export var TemplatePart; (function (TemplatePart) { const _tag = moduleTag + 'TemplatePart/'; /** * Type guard * * @category Guards */ TemplatePart.isPlaceholder = u => Placeholder.has(u); /** * Type guard * * @category Guards */ TemplatePart.isSeparator = u => Separator.has(u); /** * Namespace for a TemplatePart that represents a part of a date time * * @category Models */ let Placeholder; (function (Placeholder) { const _namespaceTag = _tag + 'Placeholder/'; const _TypeId = /*#__PURE__*/Symbol.for(_namespaceTag); /** * Type guard * * @category Guards */ Placeholder.has = u => Predicate.hasProperty(u, _TypeId); /** Prototype */ const proto = { [_TypeId]: _TypeId, [MInspectable.IdSymbol]() { return this.name; }, ... /*#__PURE__*/MInspectable.BaseProto(moduleTag), ...MPipeable.BaseProto }; const _make = params => MTypes.objectFromDataAndProto(proto, params); /** * Placeholder constructor * * @category Constructors */ Placeholder.make = name => _make({ name }); /** * Returns the `name` property of `self` * * @category Destructors */ Placeholder.name = /*#__PURE__*/Struct.get('name'); })(Placeholder = TemplatePart.Placeholder || (TemplatePart.Placeholder = {})); /** * Namespace for a TemplatePart that represents a Separator * * @category Models */ let Separator; (function (Separator) { const _namespaceTag = _tag + 'Separator/'; const _TypeId = /*#__PURE__*/Symbol.for(_namespaceTag); /** * Type guard * * @category Guards */ Separator.has = u => Predicate.hasProperty(u, _TypeId); /** Prototype */ const proto = { [_TypeId]: _TypeId, [MInspectable.IdSymbol]() { return this.value; }, ... /*#__PURE__*/MInspectable.BaseProto(moduleTag), ...MPipeable.BaseProto }; const _make = params => MTypes.objectFromDataAndProto(proto, params); /** * Placeholder constructor * * @category Constructors */ Separator.make = value => _make({ value }); /** * Returns the `value` property of `self` * * @category Destructors */ Separator.value = /*#__PURE__*/Struct.get('value'); /** * Slash Separator instance * * @category Instances */ Separator.slash = /*#__PURE__*/Separator.make('/'); /** * Backslash Separator instance * * @category Instances */ Separator.backslash = /*#__PURE__*/Separator.make('\\'); /** * Dot Separator instance * * @category Instances */ Separator.dot = /*#__PURE__*/Separator.make('.'); /** * Hyphen Separator instance * * @category Instances */ Separator.hyphen = /*#__PURE__*/Separator.make('-'); /** * Colon Separator instance * * @category Instances */ Separator.colon = /*#__PURE__*/Separator.make(':'); /** * Comma Separator instance * * @category Instances */ Separator.comma = /*#__PURE__*/Separator.make(','); /** * Space Separator instance * * @category Instances */ Separator.space = /*#__PURE__*/Separator.make(' '); })(Separator = TemplatePart.Separator || (TemplatePart.Separator = {})); })(TemplatePart || (TemplatePart = {})); /** * Type guard * * @category Guards */ export const has = u => Predicate.hasProperty(u, _TypeId); /** Prototype */ const proto = { [_TypeId]: _TypeId, [MInspectable.IdSymbol]() { return pipe(this.templateParts, Array.map(p => p.toString()), Array.join(''), MString.prepend("'"), MString.append(`' in '${this.context.name}' context`)); }, ... /*#__PURE__*/MInspectable.BaseProto(moduleTag), ...MPipeable.BaseProto }; const _make = params => MTypes.objectFromDataAndProto(proto, params); /** * Builds a DateTimeFormat from a Context `context` and an array of TemplatePart's `templateParts` * * @category Constructors */ export const make = ({ context, templateParts }) => { const getter = name => pipe(context.tokenMap, HashMap.get(name), Option.getOrThrowWith(() => new Error(`Abnormal error: no TemplatePart was defined with name '${name}'`))); const template = pipe(templateParts, Array.map(flow(MMatch.make, MMatch.when(TemplatePart.isPlaceholder, flow(TemplatePart.Placeholder.name, getter)), MMatch.when(TemplatePart.isSeparator, ({ value }) => CVTemplateSeparator.make(value)), MMatch.exhaustive)), Function.tupled(CVTemplate.make)); return _make({ context, templateParts: templateParts, _template: template }); }; /** * Returns the `context` property of `self` * * @category Destructors */ export const context = /*#__PURE__*/Struct.get('context'); /** * Returns the `templateParts` property of `self` * * @category Destructors */ export const templateParts = /*#__PURE__*/Struct.get('templateParts'); /** * Returns a function that parses a text into a DateTime according to 'self'. See DateTime.fromParts * for more information on default values and errors. * * @category Parsing */ export const toParser = self => { return flow(CVTemplate.toParser(self._template), Either.flatMap(o => CVDateTime.fromParts(o))); }; /** * Same as toParser but the returned parser returns directly a CVDateTime or throws in case of * failure * * @category Parsing */ export const toThrowingParser = /*#__PURE__*/flow(toParser, /*#__PURE__*/Function.compose(/*#__PURE__*/Either.getOrThrowWith(Function.identity))); /** * Returns a function that formats a DateTime according to 'self'. * * @category Formatting */ export const toFormatter = self => { const toParts = pipe(self._template.templateParts, Array.filterMap(flow(MMatch.make, MMatch.when(CVTemplatePart.isSeparator, () => Option.none()), MMatch.when(CVTemplatePart.isPlaceholder, flow(CVTemplatePlaceholder.name, MMatch.make, flow(MMatch.whenIs('year', flow(Tuple.make, Tuple.appendElement(CVDateTime.getYear), Option.some)), MMatch.whenIs('ordinalDay', flow(Tuple.make, Tuple.appendElement(CVDateTime.getOrdinalDay), Option.some)), MMatch.whenIs('month', flow(Tuple.make, Tuple.appendElement(CVDateTime.getMonth), Option.some)), MMatch.whenIs('monthDay', flow(Tuple.make, Tuple.appendElement(CVDateTime.getMonthDay), Option.some)), MMatch.whenIs('isoYear', flow(Tuple.make, Tuple.appendElement(CVDateTime.getIsoYear), Option.some)), MMatch.whenIs('isoWeek', flow(Tuple.make, Tuple.appendElement(CVDateTime.getIsoWeek), Option.some)), MMatch.whenIs('weekday', flow(Tuple.make, Tuple.appendElement(CVDateTime.getWeekday), Option.some)), MMatch.whenIs('hour23', flow(Tuple.make, Tuple.appendElement(CVDateTime.getHour23), Option.some)), MMatch.whenIs('hour11', flow(Tuple.make, Tuple.appendElement(CVDateTime.getHour11), Option.some))), flow(MMatch.whenIs('meridiem', flow(Tuple.make, Tuple.appendElement(CVDateTime.getMeridiem), Option.some)), MMatch.whenIs('minute', flow(Tuple.make, Tuple.appendElement(CVDateTime.getMinute), Option.some)), MMatch.whenIs('second', flow(Tuple.make, Tuple.appendElement(CVDateTime.getSecond), Option.some)), MMatch.whenIs('millisecond', flow(Tuple.make, Tuple.appendElement(CVDateTime.getMillisecond), Option.some)), MMatch.whenIs('zoneHour', flow(Tuple.make, Tuple.appendElement(CVDateTime.getZoneHour), Option.some)), MMatch.whenIs('zoneMinute', flow(Tuple.make, Tuple.appendElement(CVDateTime.getZoneMinute), Option.some)), MMatch.whenIs('zoneSecond', flow(Tuple.make, Tuple.appendElement(CVDateTime.getZoneSecond), Option.some))), MMatch.orElse(() => Option.none()))), MMatch.exhaustive)), Record.fromEntries); const formatter = CVTemplate.toFormatter(self._template); return d => pipe(toParts, Record.map(Function.apply(d)), formatter); }; /** * Same as toFormatter but the returned formatter returns directly a string or throws in case of * error * * @category Formatting */ export const toThrowingFormatter = /*#__PURE__*/flow(toFormatter, /*#__PURE__*/Function.compose(/*#__PURE__*/Either.getOrThrowWith(Function.identity))); //# sourceMappingURL=DateTimeFormat.js.map