1 // ♓️🪡 सूत्र ∷ xsd/functions.js
2 // ====================================================================
4 // Copyright © 2023 Lady [@ Lady’s Computer].
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
14 get8BitUnsignedIntegralItem
,
16 getFirstSubstringIndex
,
35 toExponentialNotation
,
40 import { div
, mod
} from "./operators.js";
46 dayTimeDurationLexicalRep
,
49 digit as lexicalDigit
,
76 scientificNotationNumeral
,
81 unsignedDecimalPtNumeral
,
82 unsignedNoDecimalPtNumeral
,
84 yearMonthDurationLexicalRep
,
85 } from "./productions.js";
95 const stringToFloat
= parseFloat
;
98 * Ensures that the provided matcher matches the provided value and
101 * ☡ This function throws if the matcher does not match.
103 * ※ This function is not exposed.
105 const ensureMatches
= (matcher
, $) => {
110 `सूत्र: Expected a ${matcher.name}, but got: ${$}.`,
116 * Ensures that the provided value with the provided name is present or
119 * ☡ This function throws if the presence of the value is not correct.
121 * ※ This function is not exposed.
123 const ensurePresence
= (name
, value
, present
= true) => {
124 if ((value
!== absent
) === !present
) {
126 `सूत्र: Expected ${name} to be ${
127 present ? "present" : "absent"
128 }, but got: ${value}.`,
136 * Ensures that the provided value is a valid, complete duration and
137 * returns an object with its months and seconds.
139 * ☡ This function throws if the provided value is not a valid,
142 * ※ This function is not exposed.
144 const duration
= ($) => {
145 const { months
, seconds
} = $;
146 if (!isIntegralNumber(months
)) {
148 `सूत्र: Expected duration to have an integer for months, but got: ${months}.`,
150 } else if (!isFiniteNumber(seconds
)) {
152 `सूत्र: Expected duration to have a finite number for seconds, but got: ${seconds}.`,
154 } else if (months
> 0 && seconds
< 0 || months
< 0 && seconds
> 0) {
156 `सूत्र: Expected seconds in duration to match polarity of months, but got: ${seconds}.`,
159 return { months
, seconds
};
164 * Ensures that the provided value is a valid
165 * date/timeSevenPropertyModel value and returns an object with its
166 * year, month, day, hour, minute, second, and timezoneOffset.
168 * ☡ This function throws if the provided value is not a valid
169 * date/timeSevenPropertyModel value.
171 * ※ This function is not exposed.
173 const date
·timeSevenPropertyModel
= ($) => {
174 if (type($) !== "object") {
176 `सूत्र: Expected a date/timeSevenPropertyModel value, but got: ${$}.`,
179 const { year
, month
, day
, hour
, minute
, second
, timezoneOffset
} =
181 if (year
!== absent
&& !isIntegralNumber(year
)) {
183 `सूत्र: Expected year to be an optional integer, but got: ${year}.`,
187 !(isIntegralNumber(month
) && month
>= 1 && month
<= 12)
190 `सूत्र: Expected month to be an optional integer between 1 and 12 inclusive, but got: ${month}.`,
194 !(isIntegralNumber(day
) && day
>= 1 && day
<= 31)
197 `सूत्र: Expected day to be an optional integer between 1 and 31 inclusive, but got: ${day}.`,
201 !(isIntegralNumber(hour
) && hour
>= 0 && hour
<= 24)
204 `सूत्र: Expected hour to be an optional integer between 0 and 24 inclusive, but got: ${hour}.`,
208 !(isIntegralNumber(minute
) && minute
>= 0 && minute
<= 59)
211 `सूत्र: Expected minute to be an optional integer between 0 and 59 inclusive, but got: ${minute}.`,
215 !(isFiniteNumber(second
) && second
>= 0 && second
< 60)
218 `सूत्र: Expected second to be an optional finite number greater than or equal to 0 and less than 60, but got: ${second}.`,
221 timezoneOffset
!== absent
&&
222 !(isIntegralNumber(timezoneOffset
) && timezoneOffset
>= -840 &&
223 timezoneOffset
<= 840)
226 `सूत्र: Expected timezoneOffset to be an optional integer between -840 and 840 inclusive, but got: ${timezoneOffset}.`,
229 month
!== absent
&& day
!== absent
&& !(
230 month
=== 2 && day
=== 29
231 ) && day
> daysInMonth(year
, month
)
234 `सूत्र: The provided day violates the day‐of‐month constraint for month ${month}: ${day}.`,
251 * Ensures that the provided value is an integer and returns it.
253 * ☡ This function throws if the provided value is not an integer.
255 * ※ This function is not exposed.
257 const integer
= ($) => {
258 if (!isIntegralNumber($)) {
259 throw new TypeError(`सूत्र: Expected an integer, but got: ${$}.`);
266 * Ensures that the provided value is a nonnegative integer and returns
269 * ☡ This function throws if the provided value is not a nonnegative
272 * ※ This function is not exposed.
274 const nonnegativeInteger
= ($) => {
275 if (!(isIntegralNumber($) && $ >= 0)) {
277 `सूत्र: Expected a nonnegative integer, but got: ${$}.`,
285 * Ensures that the provided value is a finite number and returns it.
287 * ☡ This function throws if the provided value is not a finite number.
289 * ※ This function is not exposed.
291 const decimalNumber
= ($) => {
292 if (!(isFiniteNumber($))) {
294 `सूत्र: Expected a finite number, but got: ${$}.`,
302 * Ensures that the provided value is a nonnegative finite number and
305 * ☡ This function throws if the provided value is not a nonnegative
308 * ※ This function is not exposed.
310 const nonnegativeDecimalNumber
= ($) => {
311 if (!(isFiniteNumber($) && $ >= 0)) {
313 `सूत्र: Expected a nonnegative finite number, but got: ${$}.`,
321 * Ensures that the provided value is a 32‐bit float and returns it.
323 * ☡ This function throws if the provided value is not a 32‐bit float.
325 * ※ This function is not exposed.
327 const float = ($) => {
328 if (typeof $ !== "number" || !sameValue(toFloat32($), $)) {
330 `सूत्र: Expected a float value, but got: ${$}.`,
338 * Ensures that the provided value is a number and returns it.
340 * ☡ This function throws if the provided value is not a number.
342 * ※ This function is not exposed.
344 const double = ($) => {
345 if (typeof $ !== "number") {
347 `सूत्र: Expected a double value, but got: ${$}.`,
355 * Ensures that the provided value is a hexBinary value, i·e a sequence
358 * ☡ This function throws if the provided value is not an array buffer.
360 * ※ This function is not exposed.
362 const hexBinaryValue
= ($) => {
363 if (!isArrayBuffer($)) {
365 `सूत्र: Expected a hexBinary value, but got: ${$}.`,
374 * Converts a string of 0’s and 1’s into a sequence of binary digits.
376 * ※ This function is not exposed.
381 * Converts a generator iterator into a sequence of values.
383 * ※ This function is not exposed.
388 * Converts a string into a sequence of characters.
390 * ※ This function is not exposed.
395 next
: generatorIteratorNext
,
396 } = getPrototype(function* () {}.prototype);
397 const { [ITERATOR
]: stringIterator
} = String
.prototype;
399 next
: stringIteratorNext
,
400 } = getPrototype(""[ITERATOR
]());
401 const binaryDigitIterator
= function* () {
402 for (const digit
of literalSequence(this)) {
403 yield digit
=== "0" ? 0 : 1;
406 const binaryDigitSequenceIterablePrototype
= {
410 generatorIteratorNext
,
411 call(binaryDigitIterator
, this.binaryDigits
, []),
417 const generatorSequenceIterablePrototype
= {
421 generatorIteratorNext
,
428 const literalSequenceIterablePrototype
= {
433 call(stringIterator
, this.literal
, []),
441 binaryDigitSequence
: (digits
) =>
443 binaryDigitSequenceIterablePrototype
,
444 { binaryDigits
: { value
: digits
} },
446 generatorSequence
: (generator
) =>
448 generatorSequenceIterablePrototype
,
449 { generator
: { value
: generator
} },
451 literalSequence
: (literal
) =>
453 literalSequenceIterablePrototype
,
454 { literal
: { value
: literal
} },
460 * Maps each digit to its numerical value.
462 * See <https://www.w3.org/TR/xmlschema11-2/#f-digitVal>.
464 * ☡ This function throws if the provided value is not a digit string.
466 * ※ This function is not exposed.
468 const digitValue
= (d
) => +ensureMatches(lexicalDigit
, d
);
471 * Maps a sequence of digits to the position‐weighted sum of the terms
474 * See <https://www.w3.org/TR/xmlschema11-2/#f-digitSeqVal>.
476 * ☡ This function throws if the provided value is not an iterable of
479 * ※ Although elsewhere the X·S·D specification claims that sequences
480 * count from zero, this sequence clearly must count from one.
482 * ※ This function is not exposed.
484 const digitSequenceValue
= (S
) => {
486 for (const S_i
of S
) {
487 sum
= sum
* 10 + digitValue(S_i
);
493 * Maps a sequence of digits to the position‐weighted sum of the terms
494 * numerical values, weighted appropriately for fractional digits.
496 * See <https://www.w3.org/TR/xmlschema11-2/#f-fracDigitSeqVal>.
498 * ☡ This function throws if the provided value is not an iterable of
501 * ※ The X·S·D specification erroneously specifies ·digitValue·(Si) −
502 * 10^(−i), but ·digitValue·(Si) × 10^(−i) is correct.
504 * ※ Although elsewhere the X·S·D specification claims that sequences
505 * count from zero, this sequence clearly must count from one.
507 * ※ This function is not exposed.
509 const fractionDigitSequenceValue
= (S
) => {
512 for (const S_i
of S
) {
513 sum
+= digitValue(S_i
) * 10 ** --i
;
519 * Maps a fracFrag to the appropriate fractional decimal number.
521 * See <https://www.w3.org/TR/xmlschema11-2/#f-fracFragVal>.
523 * ☡ This function throws if the provided value is not a fracFrag
526 * ※ This function is not exposed.
528 //deno-lint-ignore no-unused-vars
529 const fractionFragValue
= (N
) =>
530 fractionDigitSequenceValue(
531 literalSequence(ensureMatches(fracFrag
, N
)),
535 * Maps an unsignedNoDecimalPtNumeral to its numerical value.
537 * See <https://www.w3.org/TR/xmlschema11-2/#f-unsNoDecVal>.
539 * ☡ This function throws if the provided value is not a
540 * unsignedNoDecimalPtNumeral string.
542 export const unsignedNoDecimalMap
= (N
) =>
544 literalSequence(ensureMatches(unsignedNoDecimalPtNumeral
, N
)),
548 * Maps an noDecimalPtNumeral to its numerical value.
550 * See <https://www.w3.org/TR/xmlschema11-2/#f-noDecVal>.
552 * ☡ This function throws if the provided value is not a
553 * noDecimalPtNumeral string.
555 export const noDecimalMap
= (N
) => {
556 switch (ensureMatches(noDecimalPtNumeral
, N
)[0]) {
558 return -unsignedNoDecimalMap(substring(N
, 1)) || 0;
560 return unsignedNoDecimalMap(substring(N
, 1));
562 return unsignedNoDecimalMap(N
);
567 * Maps an unsignedDecimalPtNumeral to its numerical value.
569 * See <https://www.w3.org/TR/xmlschema11-2/#f-unsDecVal>.
571 * ☡ This function throws if the provided value is not a
572 * unsignedDecimalPtNumeral string.
574 * ※ This function makes use of the built·in Ecmascript float parsing
575 * to avoid rounding errors.
577 export const unsignedDecimalPtMap
= (D
) => {
578 // const N = substring(
579 // ensureMatches(unsignedDecimalPtNumeral, D),
581 // getFirstSubstringIndex(D, "."),
583 // const F = substring(D, N.length + 1);
585 // return unsignedNoDecimalMap(N);
586 // } else if (N === "") {
587 // return fractionFragValue(F);
589 // return unsignedNoDecimalMap(N) + fractionFragValue(F);
591 return stringToFloat(ensureMatches(unsignedDecimalPtNumeral
, D
));
595 * Maps an decimalPtNumeral to its numerical value.
597 * See <https://www.w3.org/TR/xmlschema11-2/#f-decVal>.
599 * ☡ This function throws if the provided value is not a
600 * decimalPtNumeral string.
602 export const decimalPtMap
= (N
) => {
603 switch (ensureMatches(decimalPtNumeral
, N
)[0]) {
605 return -unsignedDecimalPtMap(substring(N
, 1)) || 0;
607 return unsignedDecimalPtMap(substring(N
, 1));
609 return unsignedDecimalPtMap(N
);
614 * Maps a scientificNotationNumeral to its numerical value.
616 * See <https://www.w3.org/TR/xmlschema11-2/#f-sciVal>.
618 * ☡ This function throws if the provided value is not a
619 * scientificNotationNumeral string.
621 * ※ The X·S·D specification erroneously specifies
622 * ·unsignedDecimalPtMap·(E), but ·noDecimalMap·(E) is correct.
624 * ※ This function makes use of the built·in Ecmascript float parsing
625 * to avoid rounding errors.
627 export const scientificMap
= (N
) => {
628 // const C = substring(
629 // ensureMatches(scientificNotationNumeral, N),
633 // for (const char of literalSequence(N)) {
634 // if (char === "e" || char === "E") {
643 // const E = substring(N, C.length + 1);
644 // return getFirstSubstringIndex(N, ".") !== -1
645 // ? decimalPtMap(C) * 10 ** noDecimalMap(E)
646 // : noDecimalMap(C) * 10 ** noDecimalMap(E);
647 return stringToFloat(ensureMatches(scientificNotationNumeral
, N
)) ||
652 * Maps each integer between 0 and 9 to the corresponding digit.
654 * See <https://www.w3.org/TR/xmlschema11-2/#f-digit>.
656 * ☡ This function throws if the provided value is not an integral
657 * number between 0 and 9 inclusive.
659 * ※ This function is not exposed.
661 const digit
= (i
) => {
662 if (!(isIntegralNumber(i
) && i
>= 0 && i
<= 9)) {
664 `सूत्र: Expected an integral number between 0 and 9 inclusive, but got: ${i}.`,
672 * Maps each nonnegative integer to a sequence of integers used by
673 * ·digitSeq· to ultimately create an unsignedNoDecimalPtNumeral.
675 * See <https://www.w3.org/TR/xmlschema11-2/#f-digitRemSeq>.
677 * ☡ This function throws if the provided value is not a nonnegative
680 * ※ The sequence produced by this function is infinite.
682 * ※ This function is not exposed.
684 const digitRemainderSeq
= (i
) => {
685 nonnegativeInteger(i
);
686 return generatorSequence(function* () {
696 * Maps each nonnegative integer to a sequence of integers used by
697 * ·unsignedNoDecimalPtCanonicalMap· to create an
698 * unsignedNoDecimalPtNumeral.
700 * See <https://www.w3.org/TR/xmlschema11-2/#f-digitSeq>.
702 * ☡ This function throws if the provided value is not a nonnegative
705 * ※ The sequence produced by this function is infinite.
707 * ※ This function is not exposed.
709 const digitSeq
= (i
) => {
710 nonnegativeInteger(i
);
711 return generatorSequence(function* () {
712 for (const i_j
of digitRemainderSeq(i
)) {
719 * Maps a sequence of nonnegative integers to the index before the
722 * See <https://www.w3.org/TR/xmlschema11-2/#f-lastSigDigit>.
724 * ☡ This function throws if the values of the provided sequence are
725 * not nonnegative integers.
727 * ※ The X·S·D specification erroneously describes this function as
728 * giving the index *of* the first zero term, but it is actually the
729 * index of the last nonzero term.
731 * ※ The X·S·D specification erroneously describes this function as
732 * taking a sequence of nonnegative integers, but it is called with
733 * ·FractionDigitRemainderSeq·, which is a list of nonnegative decimal
736 * ※ This function is not exposed.
738 const lastSignificantDigit
= (s
) => {
740 for (const s_j
of s
) {
741 if (nonnegativeDecimalNumber(s_j
) === 0) {
742 return j
=== 0 ? 0 : j
- 1;
751 * Maps each nonnegative decimal number less than 1 to a sequence of
752 * decimal numbers used by ·fractionDigitSeq· to ultimately create an
753 * unsignedNoDecimalPtNumeral.
755 * See <https://www.w3.org/TR/xmlschema11-2/#f-fracDigitRemSeq>.
757 * ☡ This function throws if the provided value is not a nonnegative
758 * finite number less than 1.
760 * ※ The X·S·D specification erroneously specifies s_0 = f − 10 and
761 * s_(j+1) = (s_j ·mod· 1) − 10, but s_0 = f × 10 and s_(j+1) = (s_j
762 * ·mod· 1) × 10 is correct.
764 * ※ The implementation of this function uses string operations
765 * because Ecmascript does not (currently) have a lossless decimal
768 * ※ The sequence produced by this function is infinite.
770 * ※ This function is not exposed.
772 const FractionDigitRemainderSeq
= (f
) => {
773 if (!(isFiniteNumber(f
) && f
>= 0 && f
< 1)) {
775 `सूत्र: Expected a nonnegative finite number less than 1, but got: ${f}.`,
778 return generatorSequence(function* () {
782 s_j
= mod(s_j
, 1) * 10;
789 * Maps each nonnegative decimal number less than 1 to a sequence of
790 * integers used by ·fractionDigitsCanonicalFragmentMap· to ultimately
791 * create an unsignedNoDecimalPtNumeral.
793 * See <https://www.w3.org/TR/xmlschema11-2/#f-fracDigitSeq>.
795 * ☡ This function throws if the provided value is not a nonnegative
796 * finite number less than 1.
798 * ※ The sequence produced by this function is infinite.
800 * ※ This function is not exposed.
802 const fractionDigitSeq
= (f
) => {
803 if (!(isFiniteNumber(f
) && f
>= 0 && f
< 1)) {
805 `सूत्र: Expected a nonnegative finite number less than 1, but got: ${f}.`,
808 return generatorSequence(function* () {
809 for (const s_j
of FractionDigitRemainderSeq(f
)) {
817 * Maps each nonnegative decimal number less than 1 to a ·literal· used
818 * by ·unsignedDecimalPtCanonicalMap· to create an
819 * unsignedDecimalPtNumeral.
821 * See <https://www.w3.org/TR/xmlschema11-2/#f-fracDigitsMap>.
823 * ☡ This function throws if the provided value is not nonnegative and
826 * ※ This function is not exposed.
828 //deno-lint-ignore no-unused-vars
829 const fractionDigitsCanonicalFragmentMap
= (f
) =>
830 stringCatenate(...generatorSequence(function* () {
831 const l
= lastSignificantDigit(FractionDigitRemainderSeq(f
));
833 for (const f_j
of fractionDigitSeq(f
)) {
845 * Maps a nonnegative integer to a unsignedNoDecimalPtNumeral, its
846 * ·canonical representation·.
848 * See <https://www.w3.org/TR/xmlschema11-2/#f-unsNoDecCanFragMap>.
850 * ☡ This function throws if the provided value is not a nonnegative
853 export const unsignedNoDecimalPtCanonicalMap
= (i
) => {
854 nonnegativeInteger(i
);
855 return stringCatenate(...generatorSequence(function* () {
856 const l
= lastSignificantDigit(digitRemainderSeq(i
));
857 const digits
= new Array(l
+ 1);
859 for (const i_j
of digitSeq(i
)) {
860 digits
[l
- j
] = digit(i_j
);
868 for (j
= 0; j
<= l
; ++j
) {
875 * Maps an integer to a noDecimalPtNumeral, its ·canonical
878 * See <https://www.w3.org/TR/xmlschema11-2/#f-noDecCanMap>.
880 * ☡ This function throws if the provided value is not an integer.
882 export const noDecimalPtCanonicalMap
= (i
) =>
884 ? stringCatenate("-", unsignedNoDecimalPtCanonicalMap(-i
))
885 : unsignedNoDecimalPtCanonicalMap(i
);
888 * Maps a nonnegative decimal number to a unsignedDecimalPtNumeral, its
889 * ·canonical representation·.
891 * See <https://www.w3.org/TR/xmlschema11-2/#f-unsDecCanFragMap>.
893 * ☡ This function throws if the provided value is not a nonnegative
896 * ※ This function makes use of the built·in Ecmascript float
897 * serialization to avoid rounding errors.
899 export const unsignedDecimalPtCanonicalMap
= (n
) => {
900 // nonnegativeDecimalNumber(n);
901 // return stringCatenate(
902 // unsignedNoDecimalPtCanonicalMap(div(n, 1)),
904 // fractionDigitsCanonicalFragmentMap(mod(n, 1)),
906 const exp
= toExponentialNotation(nonnegativeDecimalNumber(n
));
907 const eIndex
= getFirstSubstringIndex(exp
, "e");
908 const exponent
= +substring(exp
, eIndex
+ 1);
909 const zeroPaddedMantissa
= stringPadEnd(
914 ) + (eIndex
> 1 ? substring(exp
, 2, eIndex
) : ""),
918 const decimalPoint
= exponent
< 0 ? 1 : exponent
+ 1;
919 return stringCatenate(
920 substring(zeroPaddedMantissa
, 0, decimalPoint
),
922 substring(zeroPaddedMantissa
, decimalPoint
),
927 * Maps a decimal number to a decimalPtNumeral, its ·canonical
930 * See <https://www.w3.org/TR/xmlschema11-2/#f-decCanFragMap>.
932 * ☡ This function throws if the provided value is not a finite number.
934 export const decimalPtCanonicalMap
= (n
) =>
936 ? stringCatenate("-", unsignedDecimalPtCanonicalMap(-n
))
937 : unsignedDecimalPtCanonicalMap(n
);
940 * Maps a nonnegative decimal number to a
941 * unsignedScientificNotationNumeral, its ·canonical representation·.
943 * See <https://www.w3.org/TR/xmlschema11-2/#f-unsSciCanFragMap>.
945 * ☡ This function throws if the provided value is not a nonnegative
948 * ※ This function makes use of the built·in Ecmascript float
949 * serialization to avoid rounding errors.
951 export const unsignedScientificCanonicalMap
= (n
) => {
952 // nonnegativeDecimalNumber(n);
953 // return stringCatenate(
954 // unsignedDecimalPtCanonicalMap(n / 10 ** div(log10(n), 1)),
956 // noDecimalPtCanonicalMap(div(log10(n), 1)),
958 const exp
= toExponentialNotation(nonnegativeDecimalNumber(n
));
959 const [mantissa
, exponent
] = stringSplit(exp
, "e");
960 return stringCatenate(
962 stringIncludes(mantissa
, ".") ? "E" : ".0E",
963 exponent
[0] === "+" ? substring(exponent
, 1) : exponent
,
968 * Maps a decimal number to a scientificNotationNumeral, its ·canonical
971 * See <https://www.w3.org/TR/xmlschema11-2/#f-sciCanFragMap>.
973 * ☡ This function throws if the provided value is not a finite number.
975 export const scientificCanonicalMap
= (n
) =>
977 ? stringCatenate("-", unsignedScientificCanonicalMap(-n
))
978 : unsignedScientificCanonicalMap(n
);
981 * Maps the ·lexical representations· of ·special values· used with
982 * some numerical datatypes to those ·special values·.
984 * See <https://www.w3.org/TR/xmlschema11-2/#f-specRepVal>.
986 * ☡ This function throws if the provided value is not a
987 * numericalSpecialRep string.
989 export const specialRepValue
= (c
) => {
990 switch (ensureMatches(numericalSpecialRep
, c
)) {
993 return positiveInfinity
;
995 return negativeInfinity
;
1002 * Maps the ·special values· used with some numerical datatypes to
1003 * their ·canonical representations·.
1005 * See <https://www.w3.org/TR/xmlschema11-2/#f-specValCanMap>.
1007 * ☡ This function throws if the provided value is not nan or positive
1008 * or negative infinity.
1010 export const specialRepCanonicalMap
= (c
) => {
1011 if (sameValue(c
, positiveInfinity
)) {
1013 } else if (sameValue(c
, negativeInfinity
)) {
1015 } else if (sameValue(c
, notANumber
)) {
1018 throw new TypeError(
1019 `सूत्र: Expected a special value, but got: ${c}.`,
1025 * Maps a decimalLexicalRep onto a decimal value.
1027 * See <https://www.w3.org/TR/xmlschema11-2/#f-decimalLexmap>.
1029 * ☡ This function throws if the provided value is not a
1030 * decimalLexicalRep string.
1032 export const decimalLexicalMap
= (LEX
) => {
1033 ensureMatches(decimalLexicalRep
, LEX
);
1034 if (noDecimalPtNumeral(LEX
)) {
1035 return noDecimalMap(LEX
);
1036 } else if (decimalPtNumeral(LEX
)) {
1037 return decimalPtMap(LEX
);
1042 * Maps a decimal to its ·canonical representation·, a
1043 * decimalLexicalRep.
1045 * See <https://www.w3.org/TR/xmlschema11-2/#f-decimalCanmap>.
1047 * ☡ This function throws if the provided value is not a finite number.
1049 export const decimalCanonicalMap
= (d
) =>
1050 isIntegralNumber(decimalNumber(d
))
1051 ? noDecimalPtCanonicalMap(d
)
1052 : decimalPtCanonicalMap(d
);
1055 * Rounds a non-zero decimal number to the nearest floating-point
1058 * See <https://www.w3.org/TR/xmlschema11-2/#f-floatPtRound>.
1060 * ☡ This function throws if the provided value is zero or is not a
1063 * ※ This function uses native Ecmascript float rounding methods and
1064 * only supports a cWidth of 24 or 53.
1066 * ※ This function is not exposed.
1068 const floatingPointRound
= (nV
, cWidth
, eMin
, eMax
) => {
1069 if (!isFiniteNumber(nV
) || nV
== 0) {
1070 throw new TypeError(
1071 `सूत्र: Expected a finite nonzero number, but got: ${nV}.`,
1073 } else if (cWidth
!== 24 && cWidth
!== 53) {
1074 throw new TypeError(
1075 `सूत्र: Unsupported cWidth: ${cWidth}.`,
1078 cWidth
=== 24 && (eMin
!== -149 || eMax
!== 104) ||
1079 cWidth
=== 53 && (eMin
!== -1074 || eMax
!== 971)
1081 throw new TypeError(
1082 `सूत्र: Unsupported eMin and eMax for cWidth: ${cWidth}.`,
1085 return cWidth
<= 24 ? toFloat32(nV
) : +nV
;
1090 * Maps a decimal number to that value rounded by some power of 10.
1092 * See <https://www.w3.org/TR/xmlschema11-2/#f-round>.
1094 * ☡ This function throws if the provided value is not a finite number.
1096 * ☡ This function throws if the provided power of 10 is not a
1097 * nonnegative integer.
1099 * ※ This function is not exposed.
1101 const round
= (n
, k
) => {
1103 nonnegativeInteger(k
);
1104 return div(n
/ 10 ** k
+ 0.5, 1) * 10 ** k
;
1108 * Maps a decimal number (c × 10e) to successive approximations.
1110 * See <https://www.w3.org/TR/xmlschema11-2/#f-round>.
1112 * ☡ This function throws if the provided values are not a nonnegative
1113 * integer, an integer, an a nonnegative integer.
1115 * ※ This function is not exposed.
1117 //deno-lint-ignore no-unused-vars
1118 const floatApprox
= (c
, e
, j
) => {
1119 nonnegativeInteger(c
);
1121 nonnegativeInteger(j
);
1122 return round(c
, j
) * 10 ** e
;
1126 * Maps a floatRep onto a float value.
1128 * See <https://www.w3.org/TR/xmlschema11-2/#f-floatLexmap>.
1130 * ☡ This function throws if the provided value is not a floatRep
1133 export const floatLexicalMap
= (LEX
) => {
1134 ensureMatches(floatRep
, LEX
);
1135 if (numericalSpecialRep(LEX
)) {
1136 return specialRepValue(LEX
);
1138 const nV
= noDecimalPtNumeral(LEX
)
1140 : decimalPtNumeral(LEX
)
1142 : scientificMap(LEX
);
1143 const v
= nV
== 0 ? 0 : floatingPointRound(nV
, 24, -149, 104);
1144 return v
== 0 ? LEX
[0] === "-" ? negativeZero
: positiveZero
: v
;
1149 * Maps a doubleRep onto a double value.
1151 * See <https://www.w3.org/TR/xmlschema11-2/#f-doubleLexmap>.
1153 * ☡ This function throws if the provided value is not a doubleRep
1156 export const doubleLexicalMap
= (LEX
) => {
1157 ensureMatches(doubleRep
, LEX
);
1158 if (numericalSpecialRep(LEX
)) {
1159 return specialRepValue(LEX
);
1161 const nV
= noDecimalPtNumeral(LEX
)
1163 : decimalPtNumeral(LEX
)
1165 : scientificMap(LEX
);
1166 const v
= nV
== 0 ? 0 : floatingPointRound(nV
, 53, -1074, 971);
1167 return v
== 0 ? LEX
[0] === "-" ? negativeZero
: positiveZero
: v
;
1172 * Maps a float to its ·canonical representation·, a floatRep.
1174 * See <https://www.w3.org/TR/xmlschema11-2/#f-floatCanmap>.
1176 * ☡ This function throws if the provided value is not a 32‐bit float.
1178 export const floatCanonicalMap
= (f
) => {
1180 return f
=== positiveInfinity
|| f
=== negativeInfinity
||
1181 sameValue(f
, notANumber
)
1182 ? specialRepCanonicalMap(f
)
1187 : scientificCanonicalMap(f
);
1191 * Maps a double to its ·canonical representation·, a doubleRep.
1193 * See <https://www.w3.org/TR/xmlschema11-2/#f-doubleCanmap>.
1195 * ☡ This function throws if the provided value is not a number.
1197 export const doubleCanonicalMap
= (f
) => {
1199 return f
=== positiveInfinity
|| f
=== negativeInfinity
||
1200 sameValue(f
, notANumber
)
1201 ? specialRepCanonicalMap(f
)
1206 : scientificCanonicalMap(f
);
1210 * Maps a duYearFrag to an integer, intended as part of the value of
1211 * the ·months· property of a duration value.
1213 * See <https://www.w3.org/TR/xmlschema11-2/#f-duYrMap>.
1215 * ☡ This function throws if the provided value is not a duYearFrag
1218 * ※ The X·S·D specification erroneously specifies the numeral as
1219 * following the letter, but it precedes it.
1221 * ※ This function is not exposed.
1223 const duYearFragmentMap
= (Y
) =>
1224 noDecimalMap(stringSlice(ensureMatches(duYearFrag
, Y
), 0, -1));
1227 * Maps a duMonthFrag to an integer, intended as part of the value of
1228 * the ·months· property of a duration value.
1230 * See <https://www.w3.org/TR/xmlschema11-2/#f-duMoMap>.
1232 * ☡ This function throws if the provided value is not a duMonthFrag
1235 * ※ The X·S·D specification erroneously specifies the numeral as
1236 * following the letter, but it precedes it.
1238 * ※ This function is not exposed.
1240 const duMonthFragmentMap
= (M
) =>
1241 noDecimalMap(stringSlice(ensureMatches(duMonthFrag
, M
), 0, -1));
1244 * Maps a duDayFrag to an integer, intended as part of the value of the
1245 * ·seconds· property of a duration value.
1247 * See <https://www.w3.org/TR/xmlschema11-2/#f-duDaMap>.
1249 * ☡ This function throws if the provided value is not a duDayFrag
1252 * ※ The X·S·D specification erroneously specifies the numeral as
1253 * following the letter, but it precedes it.
1255 * ※ This function is not exposed.
1257 const duDayFragmentMap
= (D
) =>
1258 noDecimalMap(stringSlice(ensureMatches(duDayFrag
, D
), 0, -1));
1261 * Maps a duHourFrag to an integer, intended as part of the value of
1262 * the ·seconds· property of a duration value.
1264 * See <https://www.w3.org/TR/xmlschema11-2/#f-duHrMap>.
1266 * ☡ This function throws if the provided value is not a duHourFrag
1269 * ※ The X·S·D specification erroneously specifies the numeral as
1270 * following the letter, but it precedes it.
1272 * ※ The X·S·D specification has a copypasta typo in the definition of
1273 * this function; it takes an argument H which necessarily is followed
1274 * by an "H". There is no D which necessarily begins with "D".
1276 * ※ This function is not exposed.
1278 const duHourFragmentMap
= (H
) =>
1279 noDecimalMap(stringSlice(ensureMatches(duHourFrag
, H
), 0, -1));
1282 * Maps a duMinuteFrag to an integer, intended as part of the value of
1283 * the ·seconds· property of a duration value.
1285 * See <https://www.w3.org/TR/xmlschema11-2/#f-duMiMap>.
1287 * ☡ This function throws if the provided value is not a duMinuteFrag
1290 * ※ The X·S·D specification erroneously specifies the numeral as
1291 * following the letter, but it precedes it.
1293 * ※ This function is not exposed.
1295 const duMinuteFragmentMap
= (M
) =>
1296 noDecimalMap(stringSlice(ensureMatches(duMinuteFrag
, M
), 0, -1));
1299 * Maps a duSecondFrag to an integer, intended as part of the value of
1300 * the ·seconds· property of a duration value.
1302 * See <https://www.w3.org/TR/xmlschema11-2/#f-duSeMap>.
1304 * ☡ This function throws if the provided value is not a duMinuteFrag
1307 * ※ The X·S·D specification erroneously specifies the numeral as
1308 * following the letter, but it precedes it.
1310 * ※ This function is not exposed.
1312 const duSecondFragmentMap
= (S
) =>
1313 getFirstSubstringIndex(ensureMatches(duSecondFrag
, S
), ".") !== -1
1314 ? decimalPtMap(stringSlice(S
, 0, -1))
1315 : noDecimalMap(stringSlice(S
, 0, -1));
1318 * Maps a duYearMonthFrag into an integer, intended as part of the
1319 * ·months· property of a duration value.
1321 * See <https://www.w3.org/TR/xmlschema11-2/#f-duYMMap>.
1323 * ☡ This function throws if the provided value is not a
1324 * duYearMonthFrag string.
1326 * ※ This function is not exposed.
1328 const duYearMonthFragmentMap
= (YM
) => {
1331 rawString
`(?<Y>\d+Y)?(?<M>\d+M)?`,
1333 (_
, { groups
}) => {
1338 )(ensureMatches(duYearMonthFrag
, YM
));
1339 const y
= Y
? duYearFragmentMap(Y
) : 0;
1340 const m
= M
? duMonthFragmentMap(M
) : 0;
1345 * Maps a duTimeFrag into an integer, intended as part of the ·seconds·
1346 * property of a duration value.
1348 * See <https://www.w3.org/TR/xmlschema11-2/#f-duTMap>.
1350 * ☡ This function throws if the provided value is not a duTimeFrag
1353 * ※ The X·S·D specification erroneously applies ·duDayFragmentMap· to
1354 * H; ·duHourFragmentMap· is correct.
1356 * ※ This function is not exposed.
1358 const duTimeFragmentMap
= (T
) => {
1361 rawString
`T(?<H>\d+H)?(?<M>\d+M)?(?<S>[\d.]+S)?`,
1363 (_
, { groups
}) => {
1369 )(ensureMatches(duTimeFrag
, T
));
1370 const h
= H
? duHourFragmentMap(H
) : 0;
1371 const m
= M
? duMinuteFragmentMap(M
) : 0;
1372 const s
= S
? duSecondFragmentMap(S
) : 0;
1373 return 3600 * h
+ 60 * m
+ s
;
1377 * Maps a duDayTimeFrag into a decimal number, which is the potential
1378 * value of the ·seconds· property of a duration value.
1380 * See <https://www.w3.org/TR/xmlschema11-2/#f-duDTMap>.
1382 * ☡ This function throws if the provided value is not a duDayTimeFrag
1385 * ※ This function is not exposed.
1387 const duDayTimeFragmentMap
= (DT
) => {
1390 rawString
`(?<D>\d+D)?(?<T>T.+)?`,
1392 (_
, { groups
}) => {
1397 )(ensureMatches(duDayTimeFrag
, DT
));
1398 const d
= D
? duDayFragmentMap(D
) : 0;
1399 const t
= T
? duTimeFragmentMap(T
) : 0;
1400 return 86400 * d
+ t
;
1404 * Separates the durationLexicalRep into the month part and the seconds
1405 * part, then maps them into the ·months· and ·seconds· of the duration
1408 * See <https://www.w3.org/TR/xmlschema11-2/#f-durationMap>.
1410 * ☡ This function throws if the provided value is not a
1411 * durationLexicalRep string.
1413 export const durationMap
= (DUR
) => {
1416 rawString
`-?P(?<Y>(?:\d+Y)?(?:\d+M)?)(?<D>(?:\d+D)?(?:T.+)?)`,
1418 (_
, { groups
}) => {
1423 )(ensureMatches(durationLexicalRep
, DUR
));
1424 const s
= DUR
[0] === "-" ? -1 : 1;
1426 months
: Y
? s
* duYearMonthFragmentMap(Y
) + 0 : 0, // cast −0 to 0
1427 seconds
: D
? s
* duDayTimeFragmentMap(D
) + 0 : 0, // cast −0 to 0
1432 * Maps the lexical representation into the ·months· of a
1433 * yearMonthDuration value. (A yearMonthDuration's ·seconds· is always
1434 * zero.) ·yearMonthDurationMap· is a restriction of ·durationMap·.
1436 * See <https://www.w3.org/TR/xmlschema11-2/#f-yearMonthDurationMap>.
1438 * ☡ This function throws if the provided value is not a
1439 * yearMonthDurationLexicalRep string.
1441 export const yearMonthDurationMap
= (YM
) => {
1442 const s
= YM
[0] === "-" ? -1 : 1;
1443 const Y
= substring(
1444 ensureMatches(yearMonthDurationLexicalRep
, YM
),
1448 months
: s
* duYearMonthFragmentMap(Y
) + 0, // cast −0 to 0
1454 * Maps the lexical representation into the ·seconds· of a
1455 * dayTimeDuration value. (A dayTimeDuration's ·months· is always
1456 * zero.) ·dayTimeDurationMap· is a restriction of ·durationMap·.
1458 * See <https://www.w3.org/TR/xmlschema11-2/#f-yearMonthDurationMap>.
1460 * ☡ This function throws if the provided value is not a
1461 * dayTimeDurationLexicalRep string.
1463 * ※ The X·S·D specification erroneously describes the argument as a
1464 * dayTimeDuration value rather than a dayTimeDurationLexicalRep.
1466 export const dayTimeDurationMap
= (DT
) => {
1467 const s
= DT
[0] === "-" ? -1 : 1;
1468 const D
= substring(
1469 ensureMatches(dayTimeDurationLexicalRep
, DT
),
1474 seconds
: s
* duDayTimeFragmentMap(D
) + 0, // cast −0 to 0
1479 * Maps a nonnegative integer, presumably the absolute value of the
1480 * ·months· of a duration value, to a duYearMonthFrag, a fragment of a
1481 * duration ·lexical representation·.
1483 * See <https://www.w3.org/TR/xmlschema11-2/#f-duYMCan>.
1485 * ☡ This function throws if the provided value is not a nonnegative
1488 * ※ This function is not exposed.
1490 const duYearMonthCanonicalFragmentMap
= (ym
) => {
1491 nonnegativeInteger(ym
);
1492 const y
= div(ym
, 12);
1493 const m
= mod(ym
, 12);
1494 return y
!== 0 && m
!== 0
1496 unsignedNoDecimalPtCanonicalMap(y
),
1498 unsignedNoDecimalPtCanonicalMap(m
),
1503 unsignedNoDecimalPtCanonicalMap(y
),
1507 unsignedNoDecimalPtCanonicalMap(m
),
1513 * Maps a nonnegative integer, presumably the day normalized value from
1514 * the ·seconds· of a duration value, to a duDayFrag, a fragment of a
1515 * duration ·lexical representation·.
1517 * See <https://www.w3.org/TR/xmlschema11-2/#f-duDCan>.
1519 * ☡ This function throws if the provided value is not a nonnegative
1522 * ※ Despite the description, this function does not necessarily
1523 * return a duDayFrag (it can return an empty string).
1525 * ※ This function is not exposed.
1527 const duDayCanonicalFragmentMap
= (d
) =>
1530 unsignedNoDecimalPtCanonicalMap(d
),
1536 * Maps a nonnegative integer, presumably the hour normalized value
1537 * from the ·seconds· of a duration value, to a duHourFrag, a fragment
1538 * of a duration ·lexical representation·.
1540 * See <https://www.w3.org/TR/xmlschema11-2/#f-duHCan>.
1542 * ☡ This function throws if the provided value is not a nonnegative
1545 * ※ Despite the description, this function does not necessarily
1546 * return a duHourFrag (it can return an empty string).
1548 * ※ This function is not exposed.
1550 const duHourCanonicalFragmentMap
= (h
) =>
1553 unsignedNoDecimalPtCanonicalMap(h
),
1559 * Maps a nonnegative integer, presumably the minute normalized value
1560 * from the ·seconds· of a duration value, to a duMinuteFrag, a
1561 * fragment of a duration ·lexical representation·.
1563 * See <https://www.w3.org/TR/xmlschema11-2/#f-duMCan>.
1565 * ☡ This function throws if the provided value is not a nonnegative
1568 * ※ Despite the description, this function does not necessarily
1569 * return a duMinuteFrag (it can return an empty string).
1571 * ※ This function is not exposed.
1573 const duMinuteCanonicalFragmentMap
= (m
) =>
1576 unsignedNoDecimalPtCanonicalMap(m
),
1582 * Maps a nonnegative decimal number, presumably the second normalized
1583 * value from the ·seconds· of a duration value, to a duSecondFrag, a
1584 * fragment of a duration ·lexical representation·.
1586 * See <https://www.w3.org/TR/xmlschema11-2/#f-duSCan>.
1588 * ☡ This function throws if the provided value is not a nonnegative
1591 * ※ Despite the description, this function does not necessarily
1592 * return a duSecondFrag (it can return an empty string).
1594 * ※ This function is not exposed.
1596 const duSecondCanonicalFragmentMap
= (s
) =>
1600 ? unsignedNoDecimalPtCanonicalMap(s
)
1601 : unsignedDecimalPtCanonicalMap(s
),
1607 * Maps three nonnegative numbers, presumably the hour, minute, and
1608 * second normalized values from a duration's ·seconds·, to a
1609 * duTimeFrag, a fragment of a duration ·lexical representation·.
1611 * See <https://www.w3.org/TR/xmlschema11-2/#f-duTCan>.
1613 * ☡ This function throws if either of the first two provided values
1614 * are not nonnegative integers, or if the final provided value is not
1615 * a nonnegative finite number.
1617 * ※ Despite the description, this function does not necessarily
1618 * return a duTimeFrag (it can return an empty string).
1620 * ※ This function is not exposed.
1622 const duTimeCanonicalFragmentMap
= (h
, m
, s
) =>
1623 h
!== 0 || m
!== 0 || s
!== 0
1626 duHourCanonicalFragmentMap(h
),
1627 duMinuteCanonicalFragmentMap(m
),
1628 duSecondCanonicalFragmentMap(s
),
1633 * Maps a nonnegative decimal number, presumably the absolute value of
1634 * the ·seconds· of a duration value, to a duDayTimeFrag, a fragment of
1635 * a duration ·lexical representation·.
1637 * See <https://www.w3.org/TR/xmlschema11-2/#f-duDTCan>.
1639 * ☡ This function throws if the provided value is not a nonnegative
1642 * ※ This function is not exposed.
1644 const duDayTimeCanonicalFragmentMap
= (ss
) => {
1645 nonnegativeDecimalNumber(ss
);
1646 const d
= div(ss
, 86400);
1647 const h
= div(mod(ss
, 86400), 3600);
1648 const m
= div(mod(ss
, 3600), 60);
1649 const s
= mod(ss
, 60);
1652 duDayCanonicalFragmentMap(d
),
1653 duTimeCanonicalFragmentMap(h
, m
, s
),
1659 * Maps a duration's property values to durationLexicalRep fragments
1660 * and combines the fragments into a complete durationLexicalRep.
1662 * See <https://www.w3.org/TR/xmlschema11-2/#f-durationCanMap>.
1664 * ☡ This function throws if the provided value is not a complete
1667 export const durationCanonicalMap
= (v
) => {
1668 const { months
: m
, seconds
: s
} = duration(v
);
1669 const sgn
= m
< 0 || s
< 0 ? "-" : "";
1670 return m
!== 0 && s
!== 0
1674 duYearMonthCanonicalFragmentMap(abs(m
)),
1675 duDayTimeCanonicalFragmentMap(abs(s
)),
1681 duYearMonthCanonicalFragmentMap(abs(m
)),
1686 duDayTimeCanonicalFragmentMap(abs(s
)),
1691 * Maps a yearMonthDuration's ·months· value to a
1692 * yearMonthDurationLexicalRep. (The ·seconds· value is necessarily
1693 * zero and is ignored.) ·yearMonthDurationCanonicalMap· is a
1694 * restriction of ·durationCanonicalMap·.
1696 * See <https://www.w3.org/TR/xmlschema11-2/#f-yearMonthDurationCanMap>.
1698 * ☡ This function throws if the provided value is not a complete
1699 * yearMonthDuration value.
1701 export const yearMonthDurationCanonicalMap
= (ym
) => {
1702 const { months
: m
, seconds
: s
} = duration(ym
);
1704 throw new TypeError(
1705 `सूत्र: Expected the provided yearMonthDuration to have a value of zero for seconds, but got: ${s}.`,
1708 const sgn
= m
< 0 ? "-" : "";
1709 return stringCatenate(
1712 duYearMonthCanonicalFragmentMap(abs(m
)),
1718 * Maps a dayTimeDuration's ·seconds· value to a
1719 * dayTimeDurationLexicalRep. (The ·months· value is necessarily zero
1720 * and is ignored.) ·dayTimeDurationCanonicalMap· is a restriction of
1721 * ·durationCanonicalMap·.
1723 * See <https://www.w3.org/TR/xmlschema11-2/#f-dayTimeDurationCanMap>.
1725 * ☡ This function throws if the provided value is not a complete
1726 * dayTimeDuration value.
1728 export const dayTimeDurationCanonicalMap
= (dt
) => {
1729 const { months
: m
, seconds
: s
} = duration(dt
);
1731 throw new TypeError(
1732 `सूत्र: Expected the provided dayTimeDuration to have a value of zero for months, but got: ${m}.`,
1735 const sgn
= s
< 0 ? "-" : "";
1736 return stringCatenate(
1739 duDayTimeCanonicalFragmentMap(abs(s
)),
1745 * If month (mo) is out of range, adjust month and year (yr)
1746 * accordingly; otherwise, make no change.
1748 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-normMo>.
1750 * ☡ This function throws if the provided values are not integers.
1752 * ※ This function is not exposed.
1754 const normalizeMonth
= (yr
, mo
) => {
1757 return [yr
+ div(mo
- 1, 12), mod(mo
- 1, 12) + 1];
1761 * If month (mo) is out of range, or day (da) is out of range for the
1762 * appropriate month, then adjust values accordingly, otherwise make no
1765 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-normDa>.
1767 * ☡ This function throws if the provided values are not integers.
1769 * ※ This function is not exposed.
1771 const normalizeDay
= (yr
, mo
, da
) => {
1775 [yr
, mo
] = normalizeMonth(yr
, mo
);
1776 let limit
= daysInMonth(yr
, mo
);
1777 while (da
> limit
|| da
<= 0) {
1781 [yr
, mo
] = normalizeMonth(yr
, mo
);
1782 limit
= daysInMonth(yr
, mo
);
1786 [yr
, mo
] = normalizeMonth(yr
, mo
);
1787 limit
= daysInMonth(yr
, mo
);
1791 return [yr
, mo
, da
];
1795 * Normalizes minute, hour, month, and year values to values that obey
1796 * the appropriate constraints.
1798 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-normMi>.
1800 * ☡ This function throws if the provided values are not integers.
1802 * ※ This function is not exposed.
1804 const normalizeMinute
= (yr
, mo
, da
, hr
, mi
) => {
1814 [yr
, mo
, da
] = normalizeDay(yr
, mo
, da
);
1815 return [yr
, mo
, da
, hr
, mi
];
1819 * Normalizes minute, hour, month, and year values to values that obey
1820 * the appropriate constraints. (This algorithm ignores leap seconds.)
1822 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-normSe>.
1824 * ☡ This function throws if the first five provided values are not
1825 * integers or the sixth is not a finite number.
1827 * ※ This function is not exposed.
1829 const normalizeSecond
= (yr
, mo
, da
, hr
, mi
, se
) => {
1838 [yr
, mo
, da
, hr
, mi
] = normalizeMinute(yr
, mo
, da
, hr
, mi
);
1839 return [yr
, mo
, da
, hr
, mi
, se
];
1843 * Normalizes minute, hour, month, and year values to values that obey
1844 * the appropriate constraints. (This algorithm ignores leap seconds.)
1846 * See <https://www.w3.org/TR/xmlschema11-2/#f-daysInMonth>.
1848 * ☡ This function throws if the first value is not absent or an
1849 * integer or if the second value is not an integer between 1 and 12
1852 export const daysInMonth
= (y
, m
) => {
1853 if (y
!== absent
&& !isIntegralNumber(y
)) {
1854 throw new TypeError(
1855 `सूत्र: Expected an optional integer, but got: ${y}.`,
1857 } else if (!(isIntegralNumber(m
) && m
>= 1 && m
<= 12)) {
1858 throw new TypeError(
1859 `सूत्र: Expected an integer between 1 and 12 inclusive, but got: ${m}.`,
1863 ? y
=== absent
|| y
% 4 || !(y
% 100) && y
% 400 ? 28 : 29
1864 : m
=== 4 || m
=== 6 || m
=== 9 || m
=== 11
1871 * Returns an instance of the date/timeSevenPropertyModel with property
1872 * values as specified in the arguments. If an argument is omitted, the
1873 * corresponding property is set to absent.
1875 * See <https://www.w3.org/TR/xmlschema11-2/#p-setDTFromRaw>.
1877 * ※ The X·S·D specification erroneously fails to account for the
1878 * value `"--02-29"`, which `·newDateTime·` treats as 01 March because
1879 * it assumes February has 28 days when the year is absent. This is a
1880 * correct assumption generally, but February should be treated as
1881 * having 29 days when a value of `"--02-29"` is explicity given.
1883 * ☡ This function throws if the provided values do not match the
1884 * ranges expected by the Date∕time Seven‐Property Model.
1886 export const newDateTime
= (Yr
, Mo
, Da
, Hr
, Mi
, Se
, Tz
) => {
1887 if (Yr
!== absent
&& !isIntegralNumber(Yr
)) {
1888 throw new TypeError(
1889 `सूत्र: Expected an optional integer, but got: ${Yr}.`,
1892 Mo
!== absent
&& !(isIntegralNumber(Mo
) && Mo
>= 1 && Mo
<= 12)
1894 throw new TypeError(
1895 `सूत्र: Expected an optional integer between 1 and 12 inclusive, but got: ${Mo}.`,
1898 Da
!== absent
&& !(isIntegralNumber(Da
) && Da
>= 1 && Da
<= 31)
1900 throw new TypeError(
1901 `सूत्र: Expected an optional integer between 1 and 31 inclusive, but got: ${Da}.`,
1904 Hr
!== absent
&& !(isIntegralNumber(Hr
) && Hr
>= 0 && Hr
<= 24)
1906 throw new TypeError(
1907 `सूत्र: Expected an optional integer between 0 and 24 inclusive, but got: ${Hr}.`,
1910 Mi
!== absent
&& !(isIntegralNumber(Mi
) && Mi
>= 0 && Mi
<= 59)
1912 throw new TypeError(
1913 `सूत्र: Expected an optional integer between 0 and 59 inclusive, but got: ${Mi}.`,
1916 Se
!== absent
&& !(isFiniteNumber(Se
) && Se
>= 0 && Se
< 60)
1918 throw new TypeError(
1919 `सूत्र: Expected an optional finite number greater than or equal to 0 and less than 60, but got: ${Se}.`,
1922 Tz
!== absent
&& !(isIntegralNumber(Tz
) && Tz
>= -840 && Tz
<= 840)
1924 throw new TypeError(
1925 `सूत्र: Expected an optional integer between -840 and 840 inclusive, but got: ${Tz}.`,
1928 let yr
= Yr
!== absent
? Yr
: Mo
=== 2 && Da
=== 29 ? 0 : 1;
1929 let mo
= Mo
!== absent
? Mo
: 1;
1930 let da
= Da
!== absent
? Da
: 1;
1931 let hr
= Hr
!== absent
? Hr
: 0;
1932 let mi
= Mi
!== absent
? Mi
: 0;
1933 let se
= Se
!== absent
? Se
: 0;
1934 [yr
, mo
, da
, hr
, mi
, se
] = normalizeSecond(yr
, mo
, da
, hr
, mi
, se
);
1936 year
: Yr
=== absent
? absent
: yr
,
1937 month
: Mo
=== absent
? absent
: mo
,
1938 day
: Da
=== absent
? absent
: da
,
1939 hour
: Hr
=== absent
? absent
: hr
,
1940 minute
: Mi
=== absent
? absent
: mi
,
1941 second
: Se
=== absent
? absent
: se
,
1948 * Adds a duration to a dateTime value, producing another dateTime
1951 * See <https://www.w3.org/TR/xmlschema11-2/#vp-dt-dateTimePlusDuration>.
1953 * ※ The X·S·D specification erroneously fails to account for the
1954 * value `"--02-29"`, which `·dateTimePlusDuration·` treats as 01 March
1955 * because it assumes February has 28 days when the year is absent.
1956 * This is a correct assumption generally, but February should be
1957 * treated as having 29 days when a value of `"--02-29"` is explicity
1960 * ☡ This function throws if the provided duration or
1961 * date/timeSevenPropertyModel values are not valid.
1963 * ※ Despite the name and description, this function can add a
1964 * duration to any date/timeSevenPropertyModel value.
1966 export const dateTimePlusDuration
= (du
, dt
) => {
1967 const { months
, seconds
} = duration(du
);
1976 } = date
·timeSevenPropertyModel(dt
);
1977 let yr
= year
!== absent
? year
: month
=== 2 && day
=== 29 ? 0 : 1;
1978 let mo
= month
!== absent
? month
: 1;
1979 let da
= day
!== absent
? day
: 1;
1980 let hr
= hour
!== absent
? hour
: 0;
1981 let mi
= minute
!== absent
? minute
: 0;
1982 let se
= second
!== absent
? second
: 0;
1984 [yr
, mo
] = normalizeMonth(yr
, mo
);
1985 da
= min(da
, daysInMonth(yr
, mo
));
1987 [yr
, mo
, da
, hr
, mi
, se
] = normalizeSecond(yr
, mo
, da
, hr
, mi
, se
);
1989 year
=== absent
? absent
: yr
,
1990 month
=== absent
? absent
: mo
,
1991 day
=== absent
? absent
: da
,
1992 hour
=== absent
? absent
: hr
,
1993 minute
=== absent
? absent
: mi
,
1994 second
=== absent
? absent
: se
,
2000 * Maps a date/timeSevenPropertyModel value to the decimal number
2001 * representing its position on the "time line".
2003 * See <https://www.w3.org/TR/xmlschema11-2/#vp-dt-timeOnTimeline>.
2005 * ☡ This function throws if the provided date/timeSevenPropertyModel
2006 * value is not valid.
2008 export const timeOnTimeline
= (dt
) => {
2017 } = date
·timeSevenPropertyModel(dt
);
2018 const yr
= year
=== absent
? 1971 : year
- 1;
2019 const mo
= month
=== absent
? 12 : month
;
2020 const da
= day
=== absent
? daysInMonth(yr
+ 1, mo
) - 1 : day
- 1;
2021 const hr
= hour
=== absent
? 0 : hour
;
2022 const mi
= (minute
=== absent
? 0 : minute
) -
2023 (timezoneOffset
=== absent
? 0 : timezoneOffset
);
2024 const se
= second
=== absent
? 0 : second
;
2025 let ToTI
= 31536000 * yr
;
2026 ToTI
+= 86400 * (div(yr
, 400) - div(yr
, 100) + div(yr
, 4));
2027 for (let m
= 1; m
< mo
; ++m
) {
2028 ToTI
+= 86400 * daysInMonth(yr
+ 1, m
);
2031 ToTI
+= 3600 * hr
+ 60 * mi
+ se
;
2036 * Maps a yearFrag, part of a date/timeSevenPropertyModel's ·lexical
2037 * representation·, onto an integer, presumably the ·year· property of
2038 * a date/timeSevenPropertyModel value.
2040 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-yrMap>.
2042 * ☡ This function throws if the provided value is not a yearFrag
2045 export const yearFragValue
= (YR
) =>
2046 noDecimalMap(ensureMatches(yearFrag
, YR
));
2049 * Maps a monthFrag, part of a date/timeSevenPropertyModel's ·lexical
2050 * representation·, onto an integer, presumably the ·month· property of
2051 * a date/timeSevenPropertyModel value.
2053 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-moMap>.
2055 * ☡ This function throws if the provided value is not a monthFrag
2058 export const monthFragValue
= (MO
) =>
2059 unsignedNoDecimalMap(ensureMatches(monthFrag
, MO
));
2062 * Maps a dayFrag, part of a date/timeSevenPropertyModel's ·lexical
2063 * representation·, onto an integer, presumably the ·day· property of a
2064 * date/timeSevenPropertyModel value.
2066 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-daMap>.
2068 * ☡ This function throws if the provided value is not a dayFrag
2071 export const dayFragValue
= (DA
) =>
2072 unsignedNoDecimalMap(ensureMatches(dayFrag
, DA
));
2075 * Maps a hourFrag, part of a date/timeSevenPropertyModel's ·lexical
2076 * representation·, onto an integer, presumably the ·hour· property of
2077 * a date/timeSevenPropertyModel value.
2079 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-hrMap>.
2081 * ☡ This function throws if the provided value is not a hourFrag
2084 export const hourFragValue
= (HR
) =>
2085 unsignedNoDecimalMap(ensureMatches(hourFrag
, HR
));
2088 * Maps a minuteFrag, part of a date/timeSevenPropertyModel's ·lexical
2089 * representation·, onto an integer, presumably the ·minute· property
2090 * of a date/timeSevenPropertyModel value.
2092 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-miMap>.
2094 * ☡ This function throws if the provided value is not a minuteFrag
2097 export const minuteFragValue
= (MI
) =>
2098 unsignedNoDecimalMap(ensureMatches(minuteFrag
, MI
));
2101 * Maps a secondFrag, part of a date/timeSevenPropertyModel's ·lexical
2102 * representation·, onto a decimal number, presumably the ·second·
2103 * property of a date/timeSevenPropertyModel value.
2105 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-seMap>.
2107 * ☡ This function throws if the provided value is not a secondFrag
2110 export const secondFragValue
= (SE
) =>
2111 getFirstSubstringIndex(ensureMatches(secondFrag
, SE
), ".") === -1
2112 ? unsignedNoDecimalMap(SE
)
2113 : unsignedDecimalPtMap(SE
);
2116 * Maps a timezoneFrag, part of a date/timeSevenPropertyModel's
2117 * ·lexical representation·, onto an integer, presumably the
2118 * ·timezoneOffset· property of a date/timeSevenPropertyModel value.
2120 * See <https://www.w3.org/TR/xmlschema11-2/#f-dt-tzMap>.
2122 * ※ The X·S·D specification erroneously specifies
2123 * ·unsignedDecimalPtMap·(H) and ·unsignedDecimalPtMap·(M), but
2124 * ·unsignedNoDecimalMap·(H) and ·unsignedDecimalPtMap·(M) is correct.
2126 * ☡ This function throws if the provided value is not a timezoneFrag
2129 export const timezoneFragValue
= (TZ
) => {
2130 const s
= ensureMatches(timezoneFrag
, TZ
)[0];
2136 rawString
`[+-](?<H>\d{2}):(?<M>\d{2})`,
2138 (_
, { groups
}) => {
2145 ? -(unsignedNoDecimalMap(H
) * 60 + unsignedNoDecimalMap(M
)) + 0
2146 : unsignedNoDecimalMap(H
) * 60 + unsignedNoDecimalMap(M
);
2151 * Maps a dateTimeLexicalRep to a dateTime value.
2153 * See <https://www.w3.org/TR/xmlschema11-2/#vp-dateTimeLexRep>.
2155 * ☡ This function throws if the provided value is not a
2156 * dateTimeLexicalRep string.
2158 export const dateTimeLexicalMap
= (LEX
) => {
2159 let Y
, MO
, D
, H
, MI
, S
, T
;
2161 rawString
`(?<Y>-?\d+)-(?<MO>\d+)-(?<D>\d+)T(?:24:00:00(?:\.0+)?|(?<H>\d+):(?<MI>\d+):(?<S>[\d.]+))(?<T>.+)?`,
2163 (_
, { groups
}) => {
2167 H
= groups
.H
?? absent
;
2168 MI
= groups
.MI
?? absent
;
2169 S
= groups
.S
?? absent
;
2170 T
= groups
.T
?? absent
;
2173 )(ensureMatches(dateTimeLexicalRep
, LEX
));
2174 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2190 minuteFragValue(MI
),
2197 * Maps a timeLexicalMap to a time value.
2199 * See <https://www.w3.org/TR/xmlschema11-2/#vp-timeLexRep>.
2201 * ☡ This function throws if the provided value is not a timeLexicalMap
2204 export const timeLexicalMap
= (LEX
) => {
2207 rawString
`(?:24:00:00(?:\.0+)?|(?<H>\d+):(?<MI>\d+):(?<S>[\d.]+))(?<T>.+)?`,
2209 (_
, { groups
}) => {
2210 H
= groups
.H
?? absent
;
2211 MI
= groups
.MI
?? absent
;
2212 S
= groups
.S
?? absent
;
2213 T
= groups
.T
?? absent
;
2216 )(ensureMatches(timeLexicalRep
, LEX
));
2217 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2233 minuteFragValue(MI
),
2240 * Maps a dateLexicalRep to a date value.
2242 * See <https://www.w3.org/TR/xmlschema11-2/#vp-dateLexRep>.
2244 * ☡ This function throws if the provided value is not a dateLexicalRep
2247 export const dateLexicalMap
= (LEX
) => {
2250 rawString
`(?<Y>-?\d+)-(?<M>\d+)-(?<D>\d+)(?<T>.+)?`,
2252 (_
, { groups
}) => {
2256 T
= groups
.T
?? absent
;
2259 )(ensureMatches(dateLexicalRep
, LEX
));
2260 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2273 * Maps a gYearMonthLexicalRep to a date value.
2275 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gYearMonthLexRep>.
2277 * ☡ This function throws if the provided value is not a
2278 * gYearMonthLexicalRep string.
2280 export const gYearMonthLexicalMap
= (LEX
) => {
2283 rawString
`(?<Y>-?\d+)-(?<M>\d+)(?<T>.+)?`,
2285 (_
, { groups
}) => {
2288 T
= groups
.T
?? absent
;
2291 )(ensureMatches(gYearMonthLexicalRep
, LEX
));
2292 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2305 * Maps a gYearLexicalRep to a date value.
2307 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gYearLexRep>.
2309 * ☡ This function throws if the provided value is not a
2310 * gYearLexicalRep string.
2312 export const gYearLexicalMap
= (LEX
) => {
2315 rawString
`(?<Y>-?\d+)(?<T>.+)?`,
2317 (_
, { groups
}) => {
2319 T
= groups
.T
?? absent
;
2322 )(ensureMatches(gYearLexicalRep
, LEX
));
2323 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2336 * Maps a gMonthDayLexicalRep to a date value.
2338 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gMonthDayLexRep>.
2340 * ☡ This function throws if the provided value is not a
2341 * gMonthDayLexicalRep string.
2343 export const gMonthDayLexicalMap
= (LEX
) => {
2346 rawString
`--(?<M>\d+)-(?<D>\d+)(?<T>.+)?`,
2348 (_
, { groups
}) => {
2351 T
= groups
.T
?? absent
;
2354 )(ensureMatches(gMonthDayLexicalRep
, LEX
));
2355 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2368 * Maps a gDayLexicalRep to a date value.
2370 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gDayLexRep>.
2372 * ☡ This function throws if the provided value is not a gDayLexicalRep
2375 export const gDayLexicalMap
= (LEX
) => {
2378 rawString
`---(?<D>\d+)(?<T>.+)?`,
2380 (_
, { groups
}) => {
2382 T
= groups
.T
?? absent
;
2385 )(ensureMatches(gDayLexicalRep
, LEX
));
2386 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2399 * Maps a gMonthLexicalRep to a date value.
2401 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gMonthLexRep>.
2403 * ☡ This function throws if the provided value is not a
2404 * gMonthLexicalRep string.
2406 export const gMonthLexicalMap
= (LEX
) => {
2409 rawString
`--(?<M>\d+)(?<T>.+)?`,
2411 (_
, { groups
}) => {
2413 T
= groups
.T
?? absent
;
2416 )(ensureMatches(gMonthLexicalRep
, LEX
));
2417 const tz
= T
=== absent
? absent
: timezoneFragValue(T
);
2430 * Maps a nonnegative integer less than 100 onto an unsigned
2431 * always-two-digit numeral.
2433 * See <https://www.w3.org/TR/xmlschema11-2/#f-unsTwoDigCanFragMap>.
2435 * ☡ This function throws if the provided value is not a nonnegative
2436 * integer less than 100.
2438 * ※ This function is not exposed.
2440 const unsTwoDigitCanonicalFragmentMap
= (i
) => {
2441 if (!(isIntegralNumber(i
) && i
>= 0 && i
< 100)) {
2442 throw new TypeError(
2443 `सूत्र: Expected a nonnegative integer less than 100, but got: ${i}.`,
2446 return stringCatenate(digit(div(i
, 10)), digit(mod(i
, 10)));
2451 * Maps an integer between -10000 and 10000 onto an always-four-digit numeral.
2453 * See <https://www.w3.org/TR/xmlschema11-2/#f-fourDigCanFragMap>.
2455 * ☡ This function throws if the provided value is not an integer whose
2456 * absolute value is less than 10000.
2458 * ※ This function is not exposed.
2460 const fourDigitCanonicalFragmentMap
= (i
) => {
2461 if (!(isIntegralNumber(i
) && abs(i
) < 10000)) {
2462 throw new TypeError(
2463 `सूत्र: Expected an integer whose absolute value is less than 10000, but got: ${i}.`,
2469 unsTwoDigitCanonicalFragmentMap(div(-i
, 100)),
2470 unsTwoDigitCanonicalFragmentMap(mod(-i
, 100)),
2473 unsTwoDigitCanonicalFragmentMap(div(i
, 100)),
2474 unsTwoDigitCanonicalFragmentMap(mod(i
, 100)),
2480 * Maps an integer, presumably the ·year· property of a
2481 * date/timeSevenPropertyModel value, onto a yearFrag, part of a
2482 * date/timeSevenPropertyModel's ·lexical representation·.
2484 * See <https://www.w3.org/TR/xmlschema11-2/#f-yrCanFragMap>.
2486 * ☡ This function throws if the provided value is not an integer.
2488 export const yearCanonicalFragmentMap
= (y
) =>
2489 abs(integer(y
)) > 9999
2490 ? noDecimalPtCanonicalMap(y
)
2491 : fourDigitCanonicalFragmentMap(y
);
2494 * Maps an integer, presumably the ·month· property of a
2495 * date/timeSevenPropertyModel value, onto a monthFrag, part of a
2496 * date/timeSevenPropertyModel's ·lexical representation·.
2498 * See <https://www.w3.org/TR/xmlschema11-2/#f-moCanFragMap>.
2500 * ☡ This function throws if the provided value is not an integer
2501 * between 1 and 12 inclusive.
2503 export const monthCanonicalFragmentMap
= (m
) => {
2504 if (!(isIntegralNumber(m
) && m
>= 1 && m
<= 12)) {
2505 throw new TypeError(
2506 `सूत्र: Expected an integer between 1 and 12 inclusive, but got: ${m}.`,
2509 return unsTwoDigitCanonicalFragmentMap(m
);
2514 * Maps an integer, presumably the ·day· property of a
2515 * date/timeSevenPropertyModel value, onto a dayFrag, part of a
2516 * date/timeSevenPropertyModel's ·lexical representation·.
2518 * See <https://www.w3.org/TR/xmlschema11-2/#f-daCanFragMap>.
2520 * ☡ This function throws if the provided value is not an integer
2521 * between 1 and 31 inclusive.
2523 export const dayCanonicalFragmentMap
= (d
) => {
2524 if (!(isIntegralNumber(d
) && d
>= 1 && d
<= 31)) {
2525 throw new TypeError(
2526 `सूत्र: Expected an integer between 1 and 31 inclusive, but got: ${d}.`,
2529 return unsTwoDigitCanonicalFragmentMap(d
);
2534 * Maps an integer, presumably the ·hour· property of a
2535 * date/timeSevenPropertyModel value, onto an hourFrag, part of a
2536 * date/timeSevenPropertyModel's ·lexical representation·.
2538 * See <https://www.w3.org/TR/xmlschema11-2/#f-hrCanFragMap>.
2540 * ☡ This function throws if the provided value is not an integer
2541 * between 0 and 23 inclusive.
2543 export const hourCanonicalFragmentMap
= (h
) => {
2544 if (!(isIntegralNumber(h
) && h
>= 0 && h
<= 23)) {
2545 throw new TypeError(
2546 `सूत्र: Expected an integer between 0 and 23 inclusive, but got: ${h}.`,
2549 return unsTwoDigitCanonicalFragmentMap(h
);
2554 * Maps an integer, presumably the ·minute· property of a
2555 * date/timeSevenPropertyModel value, onto a minuteFrag, part of a
2556 * date/timeSevenPropertyModel's ·lexical representation·.
2558 * See <https://www.w3.org/TR/xmlschema11-2/#f-miCanFragMap>.
2560 * ☡ This function throws if the provided value is not an integer
2561 * between 0 and 59 inclusive.
2563 export const minuteCanonicalFragmentMap
= (m
) => {
2564 if (!(isIntegralNumber(m
) && m
>= 0 && m
<= 59)) {
2565 throw new TypeError(
2566 `सूत्र: Expected an integer between 0 and 59 inclusive, but got: ${m}.`,
2569 return unsTwoDigitCanonicalFragmentMap(m
);
2574 * Maps a decimal number, presumably the ·second· property of a
2575 * date/timeSevenPropertyModel value, onto a secondFrag, part of a
2576 * date/timeSevenPropertyModel's ·lexical representation·.
2578 * See <https://www.w3.org/TR/xmlschema11-2/#f-seCanFragMap>.
2580 * ☡ This function throws if the provided value is not a nonnegative
2581 * finite number less than 60.
2583 * ※ The X·S·D specification identifies the argument to this function
2584 * as “a nonnegative decimal number less than 70”, but second values 60
2585 * or larger are not supported by X·S·D.
2587 * ※ This function makes use of the built·in Ecmascript float
2588 * serialization to avoid rounding errors.
2590 export const secondCanonicalFragmentMap
= (s
) => {
2591 if (!(isFiniteNumber(s
) && s
< 60)) {
2592 throw new TypeError(
2593 `सूत्र: Expected a nonnegative finite number less than 60, but got: ${s}.`,
2596 // return isIntegralNumber(s)
2597 // ? unsTwoDigitCanonicalFragmentMap(s)
2598 // : stringCatenate(
2599 // unsTwoDigitCanonicalFragmentMap(div(s, 1)),
2601 // fractionDigitsCanonicalFragmentMap(mod(s, 1)),
2603 return isIntegralNumber(s
)
2604 ? unsTwoDigitCanonicalFragmentMap(s
)
2606 ? stringCatenate("0", decimalPtCanonicalMap(s
))
2607 : decimalPtCanonicalMap(s
);
2612 * Maps an integer, presumably the ·timezoneOffset· property of a
2613 * date/timeSevenPropertyModel value, onto a timezoneFrag, part of a
2614 * date/timeSevenPropertyModel's ·lexical representation·.
2616 * See <https://www.w3.org/TR/xmlschema11-2/#f-tzCanFragMap>.
2618 * ☡ This function throws if the provided value is not an integer
2619 * between −840 and 840 inclusive.
2621 export const timezoneCanonicalFragmentMap
= (t
) => {
2622 if (!(isIntegralNumber(t
) && t
>= -840 && t
<= 840)) {
2623 throw new TypeError(
2624 `सूत्र: Expected an integer between −840 and 840 inclusive, but got: ${t}.`,
2627 return t
=== 0 ? "Z" : t
< 0
2630 unsTwoDigitCanonicalFragmentMap(div(-t
, 60)),
2632 unsTwoDigitCanonicalFragmentMap(mod(-t
, 60)),
2636 unsTwoDigitCanonicalFragmentMap(div(t
, 60)),
2638 unsTwoDigitCanonicalFragmentMap(mod(t
, 60)),
2644 * Maps a dateTime value to a dateTimeLexicalRep.
2646 * See <https://www.w3.org/TR/xmlschema11-2/#vp-dateTimeCanRep>.
2648 * ☡ This function throws if the provided value is not a complete
2651 export const dateTimeCanonicalMap
= (dt
) => {
2660 } = date
·timeSevenPropertyModel(dt
);
2661 ensurePresence("year", year
, true);
2662 ensurePresence("month", month
, true);
2663 ensurePresence("day", day
, true);
2664 ensurePresence("hour", hour
, true);
2665 ensurePresence("minute", minute
, true);
2666 ensurePresence("second", second
, true);
2667 const DT
= stringCatenate(
2668 yearCanonicalFragmentMap(year
),
2670 monthCanonicalFragmentMap(month
),
2672 dayCanonicalFragmentMap(day
),
2674 hourCanonicalFragmentMap(hour
),
2676 minuteCanonicalFragmentMap(minute
),
2678 secondCanonicalFragmentMap(second
),
2680 return timezoneOffset
=== absent
2682 : stringCatenate(DT
, timezoneCanonicalFragmentMap(timezoneOffset
));
2686 * Maps a time value to a timeLexicalRep.
2688 * See <https://www.w3.org/TR/xmlschema11-2/#vp-timeCanRep>.
2690 * ☡ This function throws if the provided value is not a complete time.
2692 export const timeCanonicalMap
= (ti
) => {
2701 } = date
·timeSevenPropertyModel(ti
);
2702 ensurePresence("year", year
, false);
2703 ensurePresence("month", month
, false);
2704 ensurePresence("day", day
, false);
2705 ensurePresence("hour", hour
, true);
2706 ensurePresence("minute", minute
, true);
2707 ensurePresence("second", second
, true);
2708 const T
= stringCatenate(
2709 hourCanonicalFragmentMap(hour
),
2711 minuteCanonicalFragmentMap(minute
),
2713 secondCanonicalFragmentMap(second
),
2715 return timezoneOffset
=== absent
2717 : stringCatenate(T
, timezoneCanonicalFragmentMap(timezoneOffset
));
2721 * Maps a date value to a dateLexicalRep.
2723 * See <https://www.w3.org/TR/xmlschema11-2/#vp-dateCanRep>.
2725 * ☡ This function throws if the provided value is not a complete date.
2727 export const dateCanonicalMap
= (da
) => {
2736 } = date
·timeSevenPropertyModel(da
);
2737 ensurePresence("year", year
, true);
2738 ensurePresence("month", month
, true);
2739 ensurePresence("day", day
, true);
2740 ensurePresence("hour", hour
, false);
2741 ensurePresence("minute", minute
, false);
2742 ensurePresence("second", second
, false);
2743 const D
= stringCatenate(
2744 yearCanonicalFragmentMap(year
),
2746 monthCanonicalFragmentMap(month
),
2748 dayCanonicalFragmentMap(day
),
2750 return timezoneOffset
=== absent
2752 : stringCatenate(D
, timezoneCanonicalFragmentMap(timezoneOffset
));
2756 * Maps a gYearMonth value to a gYearMonthLexicalRep.
2758 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gYearMonthCanRep>.
2760 * ☡ This function throws if the provided value is not a complete
2763 export const gYearMonthCanonicalMap
= (ym
) => {
2772 } = date
·timeSevenPropertyModel(ym
);
2773 ensurePresence("year", year
, true);
2774 ensurePresence("month", month
, true);
2775 ensurePresence("day", day
, false);
2776 ensurePresence("hour", hour
, false);
2777 ensurePresence("minute", minute
, false);
2778 ensurePresence("second", second
, false);
2779 const YM
= stringCatenate(
2780 yearCanonicalFragmentMap(year
),
2782 monthCanonicalFragmentMap(month
),
2784 return timezoneOffset
=== absent
2786 : stringCatenate(YM
, timezoneCanonicalFragmentMap(timezoneOffset
));
2790 * Maps a gYear value to a gYearLexicalRep.
2792 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gYearCanRep>.
2794 * ☡ This function throws if the provided value is not a complete
2797 export const gYearCanonicalMap
= (gY
) => {
2806 } = date
·timeSevenPropertyModel(gY
);
2807 ensurePresence("year", year
, true);
2808 ensurePresence("month", month
, false);
2809 ensurePresence("day", day
, false);
2810 ensurePresence("hour", hour
, false);
2811 ensurePresence("minute", minute
, false);
2812 ensurePresence("second", second
, false);
2813 return timezoneOffset
=== absent
2814 ? yearCanonicalFragmentMap(year
)
2816 yearCanonicalFragmentMap(year
),
2817 timezoneCanonicalFragmentMap(timezoneOffset
),
2822 * Maps a gMonthDay value to a gMonthDayLexicalRep.
2824 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gMonthDayCanRep>.
2826 * ☡ This function throws if the provided value is not a complete
2829 export const gMonthDayCanonicalMap
= (md
) => {
2838 } = date
·timeSevenPropertyModel(md
);
2839 ensurePresence("year", year
, false);
2840 ensurePresence("month", month
, true);
2841 ensurePresence("day", day
, true);
2842 ensurePresence("hour", hour
, false);
2843 ensurePresence("minute", minute
, false);
2844 ensurePresence("second", second
, false);
2845 const MD
= stringCatenate(
2847 monthCanonicalFragmentMap(month
),
2849 dayCanonicalFragmentMap(day
),
2851 return timezoneOffset
=== absent
2853 : stringCatenate(MD
, timezoneCanonicalFragmentMap(timezoneOffset
));
2857 * Maps a gDay value to a gDayLexicalRep.
2859 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gDayCanRep>.
2861 * ☡ This function throws if the provided value is not a complete gDay.
2863 export const gDayCanonicalMap
= (gD
) => {
2872 } = date
·timeSevenPropertyModel(gD
);
2873 ensurePresence("year", year
, false);
2874 ensurePresence("month", month
, false);
2875 ensurePresence("day", day
, true);
2876 ensurePresence("hour", hour
, false);
2877 ensurePresence("minute", minute
, false);
2878 ensurePresence("second", second
, false);
2879 return timezoneOffset
=== absent
2880 ? stringCatenate("---", dayCanonicalFragmentMap(day
))
2883 dayCanonicalFragmentMap(day
),
2884 timezoneCanonicalFragmentMap(timezoneOffset
),
2889 * Maps a gMonth value to a gMonthLexicalRep.
2891 * See <https://www.w3.org/TR/xmlschema11-2/#vp-gMonthCanRep>.
2893 * ☡ This function throws if the provided value is not a complete
2896 export const gMonthCanonicalMap
= (gM
) => {
2905 } = date
·timeSevenPropertyModel(gM
);
2906 ensurePresence("year", year
, false);
2907 ensurePresence("month", month
, true);
2908 ensurePresence("day", day
, false);
2909 ensurePresence("hour", hour
, false);
2910 ensurePresence("minute", minute
, false);
2911 ensurePresence("second", second
, false);
2912 return timezoneOffset
=== absent
2913 ? stringCatenate("--", dayCanonicalFragmentMap(month
))
2916 dayCanonicalFragmentMap(month
),
2917 timezoneCanonicalFragmentMap(timezoneOffset
),
2922 * Maps a ·literal· matching the stringRep production to a string
2925 * See <https://www.w3.org/TR/xmlschema11-2/#f-stringLexmap>.
2927 * ☡ This function throws if the provided value is not a stringRep
2930 export const stringLexicalMap
= (LEX
) => ensureMatches(stringRep
, LEX
);
2933 * Maps a ·literal· matching the booleanRep production to a boolean
2936 * See <https://www.w3.org/TR/xmlschema11-2/#f-booleanLexmap>.
2938 * ☡ This function throws if the provided value is not a booleanRep
2941 export const booleanLexicalMap
= (LEX
) => {
2942 ensureMatches(booleanRep
, LEX
);
2943 return LEX
=== "true" || LEX
=== "1";
2947 * Maps a string value to a stringRep.
2949 * See <https://www.w3.org/TR/xmlschema11-2/#f-stringCanmap>.
2951 * ☡ This function throws if the provided value is not a valid string.
2953 export const stringCanonicalMap
= (s
) => ensureMatches(stringRep
, s
);
2956 * Maps a boolean value to a booleanRep.
2958 * See <https://www.w3.org/TR/xmlschema11-2/#f-booleanCanmap>.
2960 * ☡ This function throws if the provided value is not a boolean.
2962 export const booleanCanonicalMap
= (b
) => {
2963 if (typeof b
!== "boolean") {
2964 throw new TypeError(`सूत्र: Expected a boolean, but got: ${b}.`);
2966 return b
? "true" : "false";
2971 * Maps a ·literal· matching the hexBinary production to a sequence of
2972 * octets in the form of a hexBinary value.
2974 * See <https://www.w3.org/TR/xmlschema11-2/#f-hexBinaryMap>.
2976 * ☡ This function throws if the provided value is not a hexBinary
2979 * ※ This function returns an `ArrayBuffer`.
2981 export const hexBinaryMap
= (LEX
) => {
2982 ensureMatches(hexBinary
, LEX
);
2983 const bufferLength
= LEX
.length
/ 2;
2984 const o
= new ArrayBuffer(bufferLength
);
2985 for (let bufferIndex
= 0, index
= 0; bufferIndex
< bufferLength
;) {
2986 set8BitIntegralItem(
2989 hexOctetMap(substring(LEX
, index
, index
= ++bufferIndex
* 2)),
2996 * Maps a ·literal· matching the hexOctet production to a single octet.
2998 * See <https://www.w3.org/TR/xmlschema11-2/#f-hexOctetMap>.
3000 * ☡ This function throws if the provided value is not a hexOctet
3003 * ※ This function is not exposed.
3005 const hexOctetMap
= (LEX
) => {
3006 const [d0
, d1
] = ensureMatches(hexOctet
, LEX
);
3009 for (const digit
of hexDigitMap(d0
)) {
3010 octet
|= digit
<< --bit
;
3012 for (const digit
of hexDigitMap(d1
)) {
3013 octet
|= digit
<< --bit
;
3019 * Maps a hexadecimal digit (a character matching the hexDigit
3020 * production) to a sequence of four binary digits.
3022 * See <https://www.w3.org/TR/xmlschema11-2/#f-hexDigitMap>.
3024 * ☡ This function throws if the provided value is not a hexDigit
3027 * ※ It would be way simpler and more efficient to just return a
3028 * single value here rather than a sequence of digits.
3030 * ※ This function is not exposed.
3032 const hexDigitMap
= (d
) => {
3033 switch (ensureMatches(hexDigit
, d
)) {
3035 return binaryDigitSequence("0000");
3037 return binaryDigitSequence("0001");
3039 return binaryDigitSequence("0010");
3041 return binaryDigitSequence("0011");
3043 return binaryDigitSequence("0100");
3045 return binaryDigitSequence("0101");
3047 return binaryDigitSequence("0110");
3049 return binaryDigitSequence("0111");
3051 return binaryDigitSequence("1000");
3053 return binaryDigitSequence("1001");
3056 return binaryDigitSequence("1010");
3059 return binaryDigitSequence("1011");
3062 return binaryDigitSequence("1100");
3065 return binaryDigitSequence("1101");
3068 return binaryDigitSequence("1110");
3071 return binaryDigitSequence("1111");
3076 * Maps a hexBinary value to a literal matching the hexBinary
3079 * See <https://www.w3.org/TR/xmlschema11-2/#f-hexBinaryCanonical>.
3081 * ☡ This function throws if the provided value is not an
3084 export const hexBinaryCanonical
= (o
) => {
3086 const length
= getByteLength(o
);
3087 return stringCatenate(
3089 ...generatorSequence(function* () {
3090 for (let index
= 0; index
< length
; ++index
) {
3091 yield hexOctetCanonical(
3092 toNumber(get8BitUnsignedIntegralItem(o
, index
)),
3100 * Maps a binary octet to a literal matching the hexOctet production.
3102 * See <https://www.w3.org/TR/xmlschema11-2/#f-hexOctetCanonical>.
3104 * ☡ This function throws if the provided value is not a hexOctet
3107 * ※ This function is not exposed.
3109 const hexOctetCanonical
= (o
) => {
3110 if (!(isIntegralNumber(o
) && o
>= 0 && o
<= 0xFF)) {
3111 throw new TypeError(
3112 `सूत्र: Expected a binary octet but got: ${o}.`,
3115 const lo
= generatorSequence(function* () {
3116 for (let i
= 1; i
<= 4; ++i
) {
3117 const offset
= 4 - i
;
3118 yield (o
& 1 << offset
) >> offset
;
3121 const hi
= generatorSequence(function* () {
3122 for (let i
= 1; i
<= 4; ++i
) {
3123 const offset
= 8 - i
;
3124 yield (o
& 1 << offset
) >> offset
;
3127 return hexDigitCanonical(hi
) + hexDigitCanonical(lo
);
3132 * Maps a four-bit sequence to a hexadecimal digit (a literal matching
3133 * the hexDigit production).
3135 * See <https://www.w3.org/TR/xmlschema11-2/#f-hexDigitCanonical>.
3137 * ☡ This function throws if the provided value is not an iterable of
3140 * ※ It would be way simpler and more efficient to just call this with
3141 * a single value rather than a sequence of digits.
3143 * ※ This function is not exposed.
3145 const hexDigitCanonical
= (d
) => {
3147 for (const digit
of d
) {
3148 if (digit
!= 0 && digit
!= 1) {
3149 throw new TypeError(
3150 `सूत्र: Expected a binary digit but got: ${digit}.`,
3153 sum
= (sum
<< 1) | digit
;