@parischap/conversions
Version:
A functional library to replace partially the native Intl API
257 lines • 9.71 kB
JavaScript
/**
* 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