@ui5/webcomponents-localization 2.20.1 → 2.20.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/generated/assets/cldr/Unicode-Data-Files-LICENSE.txt +36 -24
- package/dist/generated/assets/cldr/ar.json +624 -354
- package/dist/generated/assets/cldr/ar_EG.json +624 -354
- package/dist/generated/assets/cldr/ar_SA.json +625 -355
- package/dist/generated/assets/cldr/bg.json +339 -215
- package/dist/generated/assets/cldr/ca.json +633 -509
- package/dist/generated/assets/cldr/cnr.json +960 -653
- package/dist/generated/assets/cldr/cs.json +343 -531
- package/dist/generated/assets/cldr/cy.json +684 -1050
- package/dist/generated/assets/cldr/da.json +354 -231
- package/dist/generated/assets/cldr/de.json +458 -330
- package/dist/generated/assets/cldr/de_AT.json +459 -331
- package/dist/generated/assets/cldr/de_CH.json +522 -386
- package/dist/generated/assets/cldr/el.json +317 -152
- package/dist/generated/assets/cldr/el_CY.json +317 -152
- package/dist/generated/assets/cldr/en.json +606 -253
- package/dist/generated/assets/cldr/en_AU.json +830 -376
- package/dist/generated/assets/cldr/en_GB.json +696 -251
- package/dist/generated/assets/cldr/en_HK.json +544 -203
- package/dist/generated/assets/cldr/en_IE.json +533 -192
- package/dist/generated/assets/cldr/en_IN.json +820 -296
- package/dist/generated/assets/cldr/en_NZ.json +534 -193
- package/dist/generated/assets/cldr/en_PG.json +509 -168
- package/dist/generated/assets/cldr/en_SG.json +526 -185
- package/dist/generated/assets/cldr/en_ZA.json +529 -186
- package/dist/generated/assets/cldr/es.json +355 -230
- package/dist/generated/assets/cldr/es_AR.json +444 -288
- package/dist/generated/assets/cldr/es_BO.json +419 -264
- package/dist/generated/assets/cldr/es_CL.json +455 -300
- package/dist/generated/assets/cldr/es_CO.json +412 -257
- package/dist/generated/assets/cldr/es_MX.json +515 -352
- package/dist/generated/assets/cldr/es_PE.json +397 -234
- package/dist/generated/assets/cldr/es_UY.json +424 -269
- package/dist/generated/assets/cldr/es_VE.json +398 -243
- package/dist/generated/assets/cldr/et.json +390 -233
- package/dist/generated/assets/cldr/fa.json +510 -271
- package/dist/generated/assets/cldr/fi.json +497 -251
- package/dist/generated/assets/cldr/fr.json +339 -106
- package/dist/generated/assets/cldr/fr_BE.json +341 -108
- package/dist/generated/assets/cldr/fr_CA.json +652 -397
- package/dist/generated/assets/cldr/fr_CH.json +342 -109
- package/dist/generated/assets/cldr/fr_LU.json +339 -106
- package/dist/generated/assets/cldr/he.json +726 -904
- package/dist/generated/assets/cldr/hi.json +529 -288
- package/dist/generated/assets/cldr/hr.json +392 -383
- package/dist/generated/assets/cldr/hu.json +459 -335
- package/dist/generated/assets/cldr/id.json +379 -128
- package/dist/generated/assets/cldr/it.json +420 -301
- package/dist/generated/assets/cldr/it_CH.json +426 -307
- package/dist/generated/assets/cldr/ja.json +332 -74
- package/dist/generated/assets/cldr/kk.json +540 -240
- package/dist/generated/assets/cldr/ko.json +371 -115
- package/dist/generated/assets/cldr/lt.json +428 -545
- package/dist/generated/assets/cldr/lv.json +415 -413
- package/dist/generated/assets/cldr/mk.json +691 -559
- package/dist/generated/assets/cldr/ms.json +395 -136
- package/dist/generated/assets/cldr/nb.json +355 -234
- package/dist/generated/assets/cldr/nl.json +357 -251
- package/dist/generated/assets/cldr/nl_BE.json +428 -322
- package/dist/generated/assets/cldr/pl.json +333 -459
- package/dist/generated/assets/cldr/pt.json +419 -298
- package/dist/generated/assets/cldr/pt_PT.json +362 -231
- package/dist/generated/assets/cldr/ro.json +369 -397
- package/dist/generated/assets/cldr/ru.json +599 -368
- package/dist/generated/assets/cldr/ru_UA.json +598 -367
- package/dist/generated/assets/cldr/sk.json +343 -517
- package/dist/generated/assets/cldr/sl.json +477 -640
- package/dist/generated/assets/cldr/sr.json +478 -531
- package/dist/generated/assets/cldr/sr_Latn.json +631 -684
- package/dist/generated/assets/cldr/sv.json +395 -258
- package/dist/generated/assets/cldr/th.json +452 -199
- package/dist/generated/assets/cldr/tr.json +391 -238
- package/dist/generated/assets/cldr/uk.json +696 -342
- package/dist/generated/assets/cldr/vi.json +836 -487
- package/dist/generated/assets/cldr/zh_CN.json +358 -104
- package/dist/generated/assets/cldr/zh_HK.json +366 -113
- package/dist/generated/assets/cldr/zh_SG.json +371 -118
- package/dist/generated/assets/cldr/zh_TW.json +480 -238
- package/dist/sap/base/Event.js +2 -2
- package/dist/sap/base/Eventing.js +4 -3
- package/dist/sap/base/assert.js +1 -1
- package/dist/sap/base/config/MemoryConfigurationProvider.js +1 -1
- package/dist/sap/base/future.js +12 -0
- package/dist/sap/base/i18n/Formatting.d.ts +5 -0
- package/dist/sap/base/i18n/Formatting.js +7 -0
- package/dist/sap/base/i18n/Formatting.js.map +1 -1
- package/dist/sap/base/i18n/LanguageTag.js +18 -12
- package/dist/sap/base/i18n/Localization.d.ts +3 -0
- package/dist/sap/base/i18n/Localization.js +5 -0
- package/dist/sap/base/i18n/Localization.js.map +1 -1
- package/dist/sap/base/i18n/ResourceBundle.js +20 -0
- package/dist/sap/base/i18n/date/CalendarType.js +9 -8
- package/dist/sap/base/i18n/date/CalendarWeekNumbering.js +9 -8
- package/dist/sap/base/i18n/date/TimezoneUtils.js +170 -18
- package/dist/sap/base/i18n/date/_EnumHelper.js +37 -0
- package/dist/sap/base/strings/camelize.js +1 -1
- package/dist/sap/base/strings/formatMessage.js +6 -1
- package/dist/sap/base/util/Properties.js +12 -0
- package/dist/sap/base/util/Version.js +19 -13
- package/dist/sap/base/util/_merge.js +1 -1
- package/dist/sap/base/util/array/uniqueSort.js +1 -1
- package/dist/sap/base/util/deepClone.js +2 -2
- package/dist/sap/base/util/deepEqual.js +1 -1
- package/dist/sap/base/util/deepExtend.js +60 -0
- package/dist/sap/base/util/extend.js +1 -1
- package/dist/sap/base/util/fetch.js +8 -0
- package/dist/sap/base/util/isEmptyObject.js +1 -1
- package/dist/sap/base/util/isPlainObject.js +1 -1
- package/dist/sap/base/util/merge.js +57 -0
- package/dist/sap/base/util/mixedFetch.js +3 -0
- package/dist/sap/base/util/now.js +7 -13
- package/dist/sap/base/util/uid.js +1 -1
- package/dist/sap/ui/Device.js +27 -0
- package/dist/sap/ui/Global.js +1 -0
- package/dist/sap/ui/VersionInfo.js +14 -0
- package/dist/sap/ui/base/DataType.js +63 -12
- package/dist/sap/ui/base/DesignTime.js +11 -0
- package/dist/sap/ui/base/EventProvider.js +21 -0
- package/dist/sap/ui/base/Metadata.js +45 -10
- package/dist/sap/ui/base/Object.js +2 -2
- package/dist/sap/ui/base/OwnStatics.js +6 -0
- package/dist/sap/ui/base/SyncPromise.js +98 -0
- package/dist/sap/ui/core/AnimationMode.js +42 -0
- package/dist/sap/ui/core/CalendarType.js +2 -2
- package/dist/sap/ui/core/ControlBehavior.js +11 -0
- package/dist/sap/ui/core/Lib.js +41 -0
- package/dist/sap/ui/core/Locale.js +9 -9
- package/dist/sap/ui/core/LocaleData.js +498 -333
- package/dist/sap/ui/core/Theming.js +25 -525
- package/dist/sap/ui/core/_UrlResolver.js +11 -0
- package/dist/sap/ui/core/date/Buddhist.js +2 -2
- package/dist/sap/ui/core/date/CalendarUtils.js +14 -12
- package/dist/sap/ui/core/date/CalendarWeekNumbering.js +2 -2
- package/dist/sap/ui/core/date/Gregorian.js +2 -2
- package/dist/sap/ui/core/date/Islamic.js +2 -2
- package/dist/sap/ui/core/date/Japanese.js +2 -2
- package/dist/sap/ui/core/date/Persian.js +2 -2
- package/dist/sap/ui/core/date/UI5Date.js +80 -32
- package/dist/sap/ui/core/date/UniversalDate.js +83 -101
- package/dist/sap/ui/core/format/DateFormat.js +70 -73
- package/dist/sap/ui/core/format/FormatUtils.js +30 -0
- package/dist/sap/ui/core/format/NumberFormat.js +917 -588
- package/dist/sap/ui/core/format/TimezoneUtil.js +80 -11
- package/dist/sap/ui/core/getCompatibilityVersion.js +7 -0
- package/dist/sap/ui/core/theming/ThemeHelper.js +14 -0
- package/dist/sap/ui/security/Security.js +12 -0
- package/dist/sap/ui/util/XMLHelper.js +11 -0
- package/dist/sap/ui/util/_URL.js +1 -0
- package/dist/ui5loader-autoconfig.js +1 -0
- package/package.json +5 -5
- package/used-modules.txt +5 -0
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* OpenUI5
|
|
3
|
-
* (c) Copyright
|
|
3
|
+
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
|
|
5
5
|
*/
|
|
6
6
|
// Provides class sap.ui.core.format.NumberFormat
|
|
7
|
+
import Formatting from "../../../base/i18n/Formatting.js";
|
|
8
|
+
import Localization from "../../../base/i18n/Localization.js";
|
|
7
9
|
import BaseObject from "../../base/Object.js";
|
|
8
10
|
import Locale from "../Locale.js";
|
|
9
11
|
import LocaleData from "../LocaleData.js";
|
|
10
12
|
import Supportability from "../Supportability.js";
|
|
13
|
+
import FormatUtils from "./FormatUtils.js";
|
|
11
14
|
import Log from "../../../base/Log.js";
|
|
12
15
|
import assert from "../../../base/assert.js";
|
|
13
16
|
import extend from "../../../base/util/extend.js";
|
|
14
|
-
import Configuration from "../Configuration.js";
|
|
15
17
|
/**
|
|
16
18
|
* Format classes
|
|
17
19
|
*
|
|
@@ -38,17 +40,40 @@ var NumberFormat = BaseObject.extend("sap.ui.core.format.NumberFormat", /** @len
|
|
|
38
40
|
throw new Error();
|
|
39
41
|
}
|
|
40
42
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
43
|
+
|
|
44
|
+
// Regex for replacing the number part of a decimal or currency pattern
|
|
45
|
+
const rNumberPattern = /[0#.,]+/;
|
|
46
|
+
const rAllWhiteSpaces = /\s/g;
|
|
47
|
+
// Regex for checking whether the last character belongs to the Unicode General Category L (letter)
|
|
48
|
+
const rEndsWithLetter = /\p{L}$/u;
|
|
49
|
+
// Regex for checking whether the first character belongs to the Unicode General Category L (letter)
|
|
50
|
+
const rStartsWithLetter = /^\p{L}/u;
|
|
51
|
+
// splits a currency pattern into following matching groups:
|
|
52
|
+
// 0: complete match
|
|
53
|
+
// 1: the optional number pattern in front of the currency placeholder
|
|
54
|
+
// 2: the characters between the number pattern in front of the currency placeholder and the currency placeholder
|
|
55
|
+
// 3: the currency placeholder
|
|
56
|
+
// 4: the characters between the currency placeholder and the number pattern after the currency placeholder
|
|
57
|
+
// 5: the optional number pattern after the currency placeholder
|
|
58
|
+
const rSplitCurrencyPattern = /([0#.,]*)([^0#.,]*)(¤)([^0#.,]*)([0#.,]*)/;
|
|
59
|
+
// Regex for checking if a number has leading zeros
|
|
60
|
+
const rLeadingZeros = /^(-?)0+(\d)/;
|
|
61
|
+
// Regex for matching the number placeholder in pattern
|
|
62
|
+
const rNumPlaceHolder = /0+(\.0+)?/;
|
|
63
|
+
// Regex for checking that the given string only consists of '0' characters
|
|
64
|
+
const rOnlyZeros = /^0+$/;
|
|
65
|
+
// A regular expresssion that can be used to remove a leading "-" from a number representing zero,
|
|
66
|
+
// e.g. "-0", or "-0.00"; $1 contains the number without the leading "-"
|
|
67
|
+
const rRemoveMinusFromZero = /^-(0(?:.0+)?)$/;
|
|
68
|
+
// A regular expression that can be used to remove trailing zeros from a number
|
|
69
|
+
const rTrailingZeros = /0+$/;
|
|
70
|
+
// A regular expression that can be used to remove all RTL characters
|
|
71
|
+
// see: https://www.unicode.org/reports/tr44/#Bidi_Class_Values (Explicit Formatting Types)
|
|
72
|
+
const rAllRTLCharacters = /[\u061c\u200e\u200f\u202a\u202b\u202c]/g;
|
|
73
|
+
// A regular expression that can be used to remove the left-to-right mark character
|
|
74
|
+
const rLeftToRightMark = /\u200e/;
|
|
75
|
+
// Array of all available power of tens for short formats, max: 100 000 000 000 000
|
|
76
|
+
const aPowerOfTens = [10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000, 1000000000000, 10000000000000, 100000000000000];
|
|
52
77
|
|
|
53
78
|
/*
|
|
54
79
|
* Is used to validate existing grouping separators.
|
|
@@ -71,8 +96,8 @@ var mNumberType = {
|
|
|
71
96
|
};
|
|
72
97
|
|
|
73
98
|
/**
|
|
74
|
-
* Specifies a rounding behavior for numerical operations capable of discarding precision. Each rounding mode in
|
|
75
|
-
* significant returned digits of rounded result
|
|
99
|
+
* Specifies a rounding behavior for numerical operations capable of discarding precision. Each rounding mode in
|
|
100
|
+
* this object indicates how the least significant returned digits of rounded result are to be calculated.
|
|
76
101
|
*
|
|
77
102
|
* @public
|
|
78
103
|
* @enum {string}
|
|
@@ -80,49 +105,61 @@ var mNumberType = {
|
|
|
80
105
|
*/
|
|
81
106
|
var mRoundingMode = {
|
|
82
107
|
/**
|
|
83
|
-
* Rounding mode to round towards negative infinity
|
|
108
|
+
* Rounding mode to round towards negative infinity; examples of rounding results to one fractional digit: 0.51
|
|
109
|
+
* is rounded to 0.5, and -0.51 is rounded to -0.6.
|
|
84
110
|
* @public
|
|
85
111
|
* @type {string}
|
|
86
112
|
*/
|
|
87
113
|
FLOOR: "FLOOR",
|
|
88
114
|
/**
|
|
89
|
-
* Rounding mode to round towards positive infinity
|
|
115
|
+
* Rounding mode to round towards positive infinity; examples of rounding results to one fractional digit: 0.51
|
|
116
|
+
* is rounded to 0.6, and -0.51 is rounded to -0.5.
|
|
90
117
|
* @public
|
|
91
118
|
* @type {string}
|
|
92
119
|
*/
|
|
93
120
|
CEILING: "CEILING",
|
|
94
121
|
/**
|
|
95
|
-
* Rounding mode to round towards zero
|
|
122
|
+
* Rounding mode to round towards zero; examples of rounding results to one fractional digit: 0.59 is rounded to
|
|
123
|
+
* 0.5, and -0.59 is rounded to -0.5.
|
|
96
124
|
* @public
|
|
97
125
|
* @type {string}
|
|
98
126
|
*/
|
|
99
127
|
TOWARDS_ZERO: "TOWARDS_ZERO",
|
|
100
128
|
/**
|
|
101
|
-
* Rounding mode to round away from zero
|
|
129
|
+
* Rounding mode to round away from zero; examples of rounding results to one fractional digit: 0.51 is rounded
|
|
130
|
+
* to 0.6, and -0.51 is rounded to -0.6.
|
|
102
131
|
* @public
|
|
103
132
|
* @type {string}
|
|
104
133
|
*/
|
|
105
134
|
AWAY_FROM_ZERO: "AWAY_FROM_ZERO",
|
|
106
135
|
/**
|
|
107
|
-
* Rounding mode to round towards the nearest neighbor unless both neighbors are equidistant, in which case
|
|
136
|
+
* Rounding mode to round towards the nearest neighbor, unless both neighbors are equidistant, in which case
|
|
137
|
+
* round towards negative infinity; examples of rounding results to one fractional digit: 0.54 or 0.46 are
|
|
138
|
+
* rounded to 0.5, -0.54 or -0.46 are rounded to -0.5, 0.55 is rounded to 0.5, and -0.55 is rounded to -0.6.
|
|
108
139
|
* @public
|
|
109
140
|
* @type {string}
|
|
110
141
|
*/
|
|
111
142
|
HALF_FLOOR: "HALF_FLOOR",
|
|
112
143
|
/**
|
|
113
|
-
* Rounding mode to round towards the nearest neighbor unless both neighbors are equidistant, in which case
|
|
144
|
+
* Rounding mode to round towards the nearest neighbor, unless both neighbors are equidistant, in which case
|
|
145
|
+
* round towards positive infinity; examples of rounding results to one fractional digit: 0.54 or 0.46 are
|
|
146
|
+
* rounded to 0.5, -0.54 or -0.46 are rounded to -0.5, 0.55 is rounded to 0.6, and -0.55 is rounded to -0.5.
|
|
114
147
|
* @public
|
|
115
148
|
* @type {string}
|
|
116
149
|
*/
|
|
117
150
|
HALF_CEILING: "HALF_CEILING",
|
|
118
151
|
/**
|
|
119
|
-
* Rounding mode to round towards the nearest neighbor unless both neighbors are equidistant, in which case
|
|
152
|
+
* Rounding mode to round towards the nearest neighbor, unless both neighbors are equidistant, in which case
|
|
153
|
+
* round towards zero; examples of rounding results to one fractional digit: 0.54 or 0.46 are rounded to 0.5,
|
|
154
|
+
* -0.54 or -0.46 are rounded to -0.5, 0.55 is rounded to 0.5, and -0.55 is rounded to -0.5.
|
|
120
155
|
* @public
|
|
121
156
|
* @type {string}
|
|
122
157
|
*/
|
|
123
158
|
HALF_TOWARDS_ZERO: "HALF_TOWARDS_ZERO",
|
|
124
159
|
/**
|
|
125
|
-
* Rounding mode to round towards the nearest neighbor unless both neighbors are equidistant, in which case
|
|
160
|
+
* Rounding mode to round towards the nearest neighbor unless, both neighbors are equidistant, in which case
|
|
161
|
+
* round away from zero; examples of rounding results to one fractional digit: 0.54 or 0.46 are rounded to 0.5,
|
|
162
|
+
* -0.54 or -0.46 are rounded to -0.5, 0.55 is rounded to 0.6, and -0.55 is rounded to -0.6.
|
|
126
163
|
* @public
|
|
127
164
|
* @type {string}
|
|
128
165
|
*/
|
|
@@ -130,7 +167,77 @@ var mRoundingMode = {
|
|
|
130
167
|
};
|
|
131
168
|
|
|
132
169
|
/**
|
|
133
|
-
*
|
|
170
|
+
* Adds the summand given as a number to an decimal given as a string.
|
|
171
|
+
*
|
|
172
|
+
* @param {string} sDecimal A positive or negative decimal number as string
|
|
173
|
+
* @param {int} iSummand An integer between -9 and 9 to be added to the given decimal number
|
|
174
|
+
* @returns {string} The sum of the two numbers as a string
|
|
175
|
+
*
|
|
176
|
+
* @private
|
|
177
|
+
*/
|
|
178
|
+
NumberFormat.add = function (sDecimal, iSummand) {
|
|
179
|
+
const aParts = sDecimal.split(".");
|
|
180
|
+
let sInteger = aParts[0];
|
|
181
|
+
const sFractionPart = aParts[1];
|
|
182
|
+
const bNegative = sInteger[0] === "-";
|
|
183
|
+
if (bNegative) {
|
|
184
|
+
sInteger = sInteger.slice(1);
|
|
185
|
+
iSummand = -iSummand;
|
|
186
|
+
}
|
|
187
|
+
const aDigits = sInteger.split("").map(Number);
|
|
188
|
+
const iLastIndex = aDigits.length - 1;
|
|
189
|
+
aDigits[iLastIndex] += iSummand;
|
|
190
|
+
for (let i = iLastIndex; i >= 0; i -= 1) {
|
|
191
|
+
if (aDigits[i] >= 10) {
|
|
192
|
+
aDigits[i] = aDigits[i] % 10;
|
|
193
|
+
if (i === 0) {
|
|
194
|
+
aDigits.unshift(1);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
aDigits[i - 1] += 1;
|
|
198
|
+
} else if (aDigits[i] < 0 && i > 0) {
|
|
199
|
+
aDigits[i] = 10 + aDigits[i];
|
|
200
|
+
aDigits[i - 1] -= 1;
|
|
201
|
+
if (i === 1 && aDigits[0] === 0) {
|
|
202
|
+
aDigits.shift();
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
if (bNegative) {
|
|
210
|
+
aDigits[0] = -aDigits[0];
|
|
211
|
+
}
|
|
212
|
+
let sResult = aDigits.join("");
|
|
213
|
+
if (!sFractionPart) {
|
|
214
|
+
return sResult;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// If sResult is 0, the sign may be lost and has to be restored, e.g. "-5.123" + 5 => -5 + 5 = 0 => "-0.123"
|
|
218
|
+
sResult = sResult === "0" && bNegative ? "-0" : sResult;
|
|
219
|
+
const sResultSign = sResult[0] === "-" ? "-" : "";
|
|
220
|
+
// If both signs are equal, the fraction part can simply be appended
|
|
221
|
+
if (bNegative === !!sResultSign) {
|
|
222
|
+
return sResult + "." + sFractionPart;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// If the signs are different, aDigits contains only one digit which is different from zero; to compute the
|
|
226
|
+
// result, the result sign has to be kept, the integer part is the absolute sResult reduced by one, and the
|
|
227
|
+
// fractional part is (1 - fractional part), e.g. "2.123" - 5 => 2 - 5 = -3 => sign = "-", integer part is
|
|
228
|
+
// |-3| - 1 = 2 and fractional part is 1 - 0.123 = 0.877 without the leading "0." => "-2.877"
|
|
229
|
+
const aFractionDigits = sFractionPart.split("").map(Number);
|
|
230
|
+
for (let i = aFractionDigits.length - 1; i >= 0; i -= 1) {
|
|
231
|
+
aFractionDigits[i] = 10 - aFractionDigits[i];
|
|
232
|
+
if (i > 0) {
|
|
233
|
+
aFractionDigits[i - 1] += 1;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return sResultSign + (Math.abs(aDigits[0]) - 1) + "." + aFractionDigits.join("");
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Derives the maximum number of possible decimals from the given format option's <code>maxFractionDigits</code>
|
|
134
241
|
* and <code>decimals</code> properties.
|
|
135
242
|
*
|
|
136
243
|
* If <code>decimals</code> and <code>maxFractionDigits</code> are >= 0, then the minimum of
|
|
@@ -148,7 +255,7 @@ var mRoundingMode = {
|
|
|
148
255
|
* @private
|
|
149
256
|
* @static
|
|
150
257
|
*/
|
|
151
|
-
NumberFormat.
|
|
258
|
+
NumberFormat.getMaximumDecimals = function ({
|
|
152
259
|
decimals,
|
|
153
260
|
maxFractionDigits
|
|
154
261
|
}) {
|
|
@@ -157,25 +264,77 @@ NumberFormat.getMaximalDecimals = function ({
|
|
|
157
264
|
}
|
|
158
265
|
return decimals;
|
|
159
266
|
};
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Rounds the given number up to the smallest integer greater than or equal to the given number.
|
|
270
|
+
*
|
|
271
|
+
* @param {number|string} vNumber
|
|
272
|
+
* The number to be rounded up; it has at least one digit in front of the decimal point in case of type "string"
|
|
273
|
+
* @returns {number|string}
|
|
274
|
+
* The smallest integer greater than or equal to the given number; the returned type is the same as the type of
|
|
275
|
+
* the given number
|
|
276
|
+
*/
|
|
277
|
+
function ceil(vNumber) {
|
|
278
|
+
if (typeof vNumber === "number") {
|
|
279
|
+
return Math.ceil(vNumber);
|
|
280
|
+
}
|
|
281
|
+
const [sIntegerPart, sFractionPart = "0"] = vNumber.split(".");
|
|
282
|
+
return rOnlyZeros.test(sFractionPart) || sIntegerPart[0] === "-" ? sIntegerPart : NumberFormat.add(sIntegerPart, 1);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Rounds the given number down to the largest integer less than or equal to the given number.
|
|
287
|
+
*
|
|
288
|
+
* @param {number|string} vNumber
|
|
289
|
+
* The number to be rounded down; it has at least one digit in front of the decimal point in case of type "string"
|
|
290
|
+
* @returns {number|string}
|
|
291
|
+
* The largest integer less than or equal to the given number; the returned type is the same as the type of the
|
|
292
|
+
* given number
|
|
293
|
+
*/
|
|
294
|
+
function floor(vNumber) {
|
|
295
|
+
if (typeof vNumber === "number") {
|
|
296
|
+
return Math.floor(vNumber);
|
|
297
|
+
}
|
|
298
|
+
const [sIntegerPart, sFractionPart = "0"] = vNumber.split(".");
|
|
299
|
+
return rOnlyZeros.test(sFractionPart) || sIntegerPart[0] !== "-" ? sIntegerPart : NumberFormat.add(sIntegerPart, -1);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Adds 0.5 to or subtracts 0.5 from the given number.
|
|
304
|
+
*
|
|
305
|
+
* @param {number|string} vNumber
|
|
306
|
+
* The number to be increased or decreased by 0.5
|
|
307
|
+
* @param {boolean} bIncrease
|
|
308
|
+
* Whether to increase the number by 0.5; otherwise the number is decreased by 0.5
|
|
309
|
+
* @returns {number|string}
|
|
310
|
+
* The number increased or decreased by 0.5; the returned type is the same as the type of the given number
|
|
311
|
+
*/
|
|
312
|
+
function increaseOrDecreaseByHalf(vNumber, bIncrease) {
|
|
313
|
+
if (typeof vNumber === "number") {
|
|
314
|
+
return bIncrease ? vNumber + 0.5 : vNumber - 0.5;
|
|
315
|
+
}
|
|
316
|
+
vNumber = NumberFormat._shiftDecimalPoint(vNumber, 1);
|
|
317
|
+
vNumber = NumberFormat.add(vNumber, bIncrease ? 5 : -5);
|
|
318
|
+
return NumberFormat._shiftDecimalPoint(vNumber, -1);
|
|
319
|
+
}
|
|
320
|
+
const mRoundingFunction = {
|
|
321
|
+
[mRoundingMode.FLOOR]: floor,
|
|
322
|
+
[mRoundingMode.CEILING]: ceil,
|
|
323
|
+
[mRoundingMode.TOWARDS_ZERO]: vNumber => vNumber > 0 ? floor(vNumber) : ceil(vNumber),
|
|
324
|
+
[mRoundingMode.AWAY_FROM_ZERO]: vNumber => vNumber > 0 ? ceil(vNumber) : floor(vNumber),
|
|
325
|
+
[mRoundingMode.HALF_TOWARDS_ZERO]: vNumber => {
|
|
326
|
+
const bPositive = vNumber > 0;
|
|
327
|
+
vNumber = increaseOrDecreaseByHalf(vNumber, !bPositive);
|
|
328
|
+
return bPositive ? ceil(vNumber) : floor(vNumber);
|
|
329
|
+
},
|
|
330
|
+
[mRoundingMode.HALF_AWAY_FROM_ZERO]: vNumber => {
|
|
331
|
+
const bPositive = vNumber > 0;
|
|
332
|
+
vNumber = increaseOrDecreaseByHalf(vNumber, bPositive);
|
|
333
|
+
return bPositive ? floor(vNumber) : ceil(vNumber);
|
|
334
|
+
},
|
|
335
|
+
[mRoundingMode.HALF_FLOOR]: vNumber => ceil(increaseOrDecreaseByHalf(vNumber, false)),
|
|
336
|
+
[mRoundingMode.HALF_CEILING]: vNumber => floor(increaseOrDecreaseByHalf(vNumber, true))
|
|
177
337
|
};
|
|
178
|
-
mRoundingFunction[mRoundingMode.HALF_CEILING] = Math.round;
|
|
179
338
|
NumberFormat.RoundingMode = mRoundingMode;
|
|
180
339
|
|
|
181
340
|
/*
|
|
@@ -322,6 +481,42 @@ NumberFormat.oDefaultUnitFormat = {
|
|
|
322
481
|
showScale: true
|
|
323
482
|
};
|
|
324
483
|
|
|
484
|
+
/**
|
|
485
|
+
* Checks the given format options if decimal padding is allowed and if the decimal padding value is supported.
|
|
486
|
+
*
|
|
487
|
+
* @param {object} [oFormatOptions]
|
|
488
|
+
* The format options to be checked
|
|
489
|
+
* @param {int} [oFormatOptions.decimalPadding]
|
|
490
|
+
* The format option decimal padding
|
|
491
|
+
* @param {boolean} [oFormatOptions.showMeasure]
|
|
492
|
+
* The format option show measure
|
|
493
|
+
* @param {string} [oFormatOptions.style]
|
|
494
|
+
* The format option style
|
|
495
|
+
* @param {boolean} [bDecimalPaddingSupported=true]
|
|
496
|
+
* Whether decimal padding is supported
|
|
497
|
+
* @param {boolean} [bShowMeasureMustBeFalse=false]
|
|
498
|
+
* Whether the format option <code>showMeasure</code> must be set to false
|
|
499
|
+
* @throws {Error} If decimal padding cannot be used or the given decimal padding value is not supported
|
|
500
|
+
*
|
|
501
|
+
* @private
|
|
502
|
+
* @static
|
|
503
|
+
*/
|
|
504
|
+
NumberFormat.checkDecimalPadding = function (oFormatOptions, bDecimalPaddingSupported = true, bShowMeasureMustBeFalse = false) {
|
|
505
|
+
const iDecimalPadding = oFormatOptions?.decimalPadding;
|
|
506
|
+
if (!bDecimalPaddingSupported && iDecimalPadding !== undefined) {
|
|
507
|
+
throw new Error("Unsupported format option: 'decimalPadding' cannot be used with an integer or percent" + " instance of sap.ui.core.format.NumberFormat");
|
|
508
|
+
}
|
|
509
|
+
if (bShowMeasureMustBeFalse && iDecimalPadding && oFormatOptions?.showMeasure !== false) {
|
|
510
|
+
throw new Error("The format option 'decimalPadding' can only be used if the format option" + " 'showMeasure' is set to false");
|
|
511
|
+
}
|
|
512
|
+
if (iDecimalPadding < 1) {
|
|
513
|
+
throw new Error("The format option 'decimalPadding' must have a value greater than 0");
|
|
514
|
+
}
|
|
515
|
+
if (iDecimalPadding > 0 && (oFormatOptions?.style === "short" || oFormatOptions?.style === "long")) {
|
|
516
|
+
throw new Error("The format option 'decimalPadding' can only be used if the format option" + " 'style' is not set to 'short' or 'long'");
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
|
|
325
520
|
/**
|
|
326
521
|
* An alias for {@link #getFloatInstance}.
|
|
327
522
|
*
|
|
@@ -338,9 +533,6 @@ NumberFormat.getInstance = function (oFormatOptions, oLocale) {
|
|
|
338
533
|
/**
|
|
339
534
|
* Get a float instance of the NumberFormat, which can be used for formatting.
|
|
340
535
|
*
|
|
341
|
-
* If no locale is given, the currently configured
|
|
342
|
-
* {@link sap.ui.core.Configuration.FormatSettings#getFormatLocale formatLocale} will be used.
|
|
343
|
-
*
|
|
344
536
|
* <p>
|
|
345
537
|
* This instance has HALF_AWAY_FROM_ZERO set as default rounding mode.
|
|
346
538
|
* Please set the roundingMode property in oFormatOptions to change the
|
|
@@ -361,6 +553,16 @@ NumberFormat.getInstance = function (oFormatOptions, oLocale) {
|
|
|
361
553
|
*
|
|
362
554
|
* @param {object} [oFormatOptions] The option object, which supports the following parameters.
|
|
363
555
|
* If no options are given, default values according to the type and locale settings are used.
|
|
556
|
+
* @param {int} [oFormatOptions.decimalPadding]
|
|
557
|
+
* The target length of places after the decimal separator; if the number has fewer decimal places than given in
|
|
558
|
+
* this option, it is padded with whitespaces at the end up to the target length. An additional whitespace
|
|
559
|
+
* character for the decimal separator is added for a number without any decimals.
|
|
560
|
+
* <b>Note:</b> This format option is only allowed if the following conditions apply:
|
|
561
|
+
* <ul>
|
|
562
|
+
* <li>It has a value greater than 0.</li>
|
|
563
|
+
* <li>The <code>oFormatOptions.style</code> format option is <b>not</b> set to <code>"short"</code> or
|
|
564
|
+
* <code>"long"</code>.</li>
|
|
565
|
+
* </ul>
|
|
364
566
|
* @param {int} [oFormatOptions.decimals] defines the number of decimal digits
|
|
365
567
|
* @param {string} [oFormatOptions.decimalSeparator] defines the character used as decimal separator.
|
|
366
568
|
* Note: <code>decimalSeparator</code> must always be different from <code>groupingSeparator</code>.
|
|
@@ -373,11 +575,14 @@ NumberFormat.getInstance = function (oFormatOptions, oLocale) {
|
|
|
373
575
|
* @param {int} [oFormatOptions.groupingBaseSize=3] defines the grouping base size in digits if
|
|
374
576
|
* it is different from the grouping size (e.g. Indian grouping)
|
|
375
577
|
* @param {boolean} [oFormatOptions.groupingEnabled=true] defines whether grouping is enabled
|
|
376
|
-
* (grouping separators are shown)
|
|
578
|
+
* (grouping separators are shown).
|
|
579
|
+
* <b>Note:</b> Grouping is disabled if the <code>groupingSize</code> format option is set to
|
|
580
|
+
* a non-positive value.
|
|
377
581
|
* @param {string} [oFormatOptions.groupingSeparator] defines the character used as grouping separator.
|
|
378
582
|
* Note: <code>groupingSeparator</code> must always be different from <code>decimalSeparator</code>.
|
|
379
583
|
* @param {int} [oFormatOptions.groupingSize=3] defines the grouping size in digits; the default
|
|
380
|
-
* is <code>3</code>.
|
|
584
|
+
* is <code>3</code>.
|
|
585
|
+
* <b>Note:</b> If this format option is set to a non-positive value, grouping will be disabled entirely.
|
|
381
586
|
* @param {int} [oFormatOptions.maxFractionDigits=99] defines the maximum number of decimal digits
|
|
382
587
|
* @param {int} [oFormatOptions.maxIntegerDigits=99] defines the maximum number of non-decimal digits.
|
|
383
588
|
* If the number exceeds this maximum, e.g. 1e+120, "?" characters are shown instead of digits.
|
|
@@ -390,19 +595,25 @@ NumberFormat.getInstance = function (oFormatOptions, oLocale) {
|
|
|
390
595
|
* to "0.005".
|
|
391
596
|
* @param {string} [oFormatOptions.pattern] CLDR number pattern which is used to format the number
|
|
392
597
|
* @param {string} [oFormatOptions.plusSign] defines the used plus symbol
|
|
393
|
-
* @param {int} [oFormatOptions.precision]
|
|
394
|
-
* is
|
|
598
|
+
* @param {int} [oFormatOptions.precision] The maximum number of digits in the formatted representation of a number;
|
|
599
|
+
* if the <code>precision</code> is less than the overall length of the number, its fractional part is truncated
|
|
600
|
+
* through rounding. As the <code>precision</code> only affects the rounding of a number, its integer part can
|
|
601
|
+
* retain more digits than defined by this parameter.
|
|
602
|
+
* <b>Example:</b> With a <code>precision</code> of 2, <code>234.567</code> is formatted to <code>235</code>.
|
|
603
|
+
* <b>Note:</b> The formatted output may differ depending on locale.
|
|
395
604
|
* @param {boolean} [oFormatOptions.preserveDecimals=false] Whether {@link #format} preserves
|
|
396
605
|
* decimal digits except trailing zeros in case there are more decimals than the
|
|
397
606
|
* <code>maxFractionDigits</code> format option allows.
|
|
398
607
|
* If decimals are not preserved, the formatted number is rounded to <code>maxFractionDigits</code>.
|
|
399
608
|
* @param {sap.ui.core.format.NumberFormat.RoundingMode} [oFormatOptions.roundingMode=HALF_AWAY_FROM_ZERO]
|
|
400
|
-
*
|
|
401
|
-
* defined by
|
|
609
|
+
* Specifies the rounding behavior for discarding the digits after the maximum fraction digits
|
|
610
|
+
* defined by <code>maxFractionDigits</code>.
|
|
402
611
|
* This can be assigned
|
|
403
612
|
* <ul>
|
|
404
613
|
* <li>by value in {@link sap.ui.core.format.NumberFormat.RoundingMode RoundingMode},</li>
|
|
405
|
-
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
614
|
+
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
615
|
+
* number of decimal digits that should be reserved. <b>Using a function is deprecated since 1.121.0</b>;
|
|
616
|
+
* string based numbers are not rounded via this custom function.</li>
|
|
406
617
|
* </ul>
|
|
407
618
|
* @param {int} [oFormatOptions.shortDecimals] defines the number of decimal in the shortened format string. If this isn't specified, the 'decimals' options is used
|
|
408
619
|
* @param {int} [oFormatOptions.shortLimit] only use short number formatting for values above this limit
|
|
@@ -416,24 +627,26 @@ NumberFormat.getInstance = function (oFormatOptions, oLocale) {
|
|
|
416
627
|
* numbers are formatted into compact forms. When this option is set, the default value of the
|
|
417
628
|
* 'precision' option is set to 2. This can be changed by setting either min/maxFractionDigits,
|
|
418
629
|
* decimals, shortDecimals, or the 'precision' option itself.
|
|
419
|
-
* @param {sap.ui.core.Locale} [oLocale]
|
|
630
|
+
* @param {sap.ui.core.Locale} [oLocale]
|
|
631
|
+
* The locale to get the formatter for; if no locale is given, a locale for the currently configured language is
|
|
632
|
+
* used; see {@link module:sap/base/i18n/Formatting.getLanguageTag Formatting.getLanguageTag}
|
|
420
633
|
* @return {sap.ui.core.format.NumberFormat} float instance of the NumberFormat
|
|
634
|
+
* @throws {Error} If the <code>oFormatOptions.decimalPadding</code> is set but is not allowed
|
|
421
635
|
* @static
|
|
422
636
|
* @public
|
|
423
637
|
*/
|
|
424
638
|
NumberFormat.getFloatInstance = function (oFormatOptions, oLocale) {
|
|
425
|
-
|
|
426
|
-
|
|
639
|
+
NumberFormat.checkDecimalPadding(oFormatOptions);
|
|
640
|
+
const oFormat = NumberFormat.createInstance(oFormatOptions, oLocale);
|
|
641
|
+
const oLocaleFormatOptions = oFormat.getLocaleFormatOptions(mNumberType.FLOAT);
|
|
427
642
|
oFormat.oFormatOptions = extend({}, this.oDefaultFloatFormat, oLocaleFormatOptions, oFormat.oOriginalFormatOptions);
|
|
643
|
+
oFormat.checkGroupingFormatOptions();
|
|
428
644
|
return oFormat;
|
|
429
645
|
};
|
|
430
646
|
|
|
431
647
|
/**
|
|
432
648
|
* Get an integer instance of the NumberFormat, which can be used for formatting.
|
|
433
649
|
*
|
|
434
|
-
* If no locale is given, the currently configured
|
|
435
|
-
* {@link sap.ui.core.Configuration.FormatSettings#getFormatLocale formatLocale} will be used.
|
|
436
|
-
*
|
|
437
650
|
* <p>
|
|
438
651
|
* This instance has TOWARDS_ZERO set as default rounding mode.
|
|
439
652
|
* Please set the roundingMode property in oFormatOptions to change the
|
|
@@ -453,6 +666,7 @@ NumberFormat.getFloatInstance = function (oFormatOptions, oLocale) {
|
|
|
453
666
|
*
|
|
454
667
|
* @param {object} [oFormatOptions] The option object, which supports the following parameters.
|
|
455
668
|
* If no options are given, default values according to the type and locale settings are used.
|
|
669
|
+
* @param {int} [oFormatOptions.decimalPadding] Not supported.
|
|
456
670
|
* @param {int} [oFormatOptions.decimals] defines the number of decimal digits
|
|
457
671
|
* @param {string} [oFormatOptions.decimalSeparator] defines the character used as decimal separator.
|
|
458
672
|
* Note: <code>decimalSeparator</code> must always be different from <code>groupingSeparator</code>.
|
|
@@ -465,11 +679,14 @@ NumberFormat.getFloatInstance = function (oFormatOptions, oLocale) {
|
|
|
465
679
|
* @param {int} [oFormatOptions.groupingBaseSize=3] defines the grouping base size in digits if
|
|
466
680
|
* it is different from the grouping size (e.g. Indian grouping)
|
|
467
681
|
* @param {boolean} [oFormatOptions.groupingEnabled=false] defines whether grouping is enabled
|
|
468
|
-
* (grouping separators are shown)
|
|
682
|
+
* (grouping separators are shown).
|
|
683
|
+
* <b>Note:</b> Grouping is disabled if the <code>groupingSize</code> format option is set to
|
|
684
|
+
* a non-positive value.
|
|
469
685
|
* @param {string} [oFormatOptions.groupingSeparator] defines the character used as grouping separator.
|
|
470
686
|
* Note: <code>groupingSeparator</code> must always be different from <code>decimalSeparator</code>.
|
|
471
687
|
* @param {int} [oFormatOptions.groupingSize=3] defines the grouping size in digits; the default
|
|
472
|
-
* is <code>3</code>.
|
|
688
|
+
* is <code>3</code>.
|
|
689
|
+
* <b>Note:</b> If this format option is set to a non-positive value, grouping will be disabled entirely.
|
|
473
690
|
* @param {int} [oFormatOptions.maxFractionDigits=0] defines the maximum number of decimal digits
|
|
474
691
|
* @param {int} [oFormatOptions.maxIntegerDigits=99] defines the maximum number of non-decimal digits.
|
|
475
692
|
* If the number exceeds this maximum, e.g. 1e+120, "?" characters are shown instead of digits.
|
|
@@ -482,19 +699,28 @@ NumberFormat.getFloatInstance = function (oFormatOptions, oLocale) {
|
|
|
482
699
|
* to "5000".
|
|
483
700
|
* @param {string} [oFormatOptions.pattern] CLDR number pattern which is used to format the number
|
|
484
701
|
* @param {string} [oFormatOptions.plusSign] defines the used plus symbol
|
|
485
|
-
* @param {int} [oFormatOptions.precision]
|
|
486
|
-
*
|
|
702
|
+
* @param {int} [oFormatOptions.precision] <b>Note:</b> Only considered if the number format leads to a
|
|
703
|
+
* representation with decimal places, e.g. if the option <code>style: "short"</code> is set.
|
|
704
|
+
* The maximum number of digits in the formatted representation of a number; if the <code>precision</code> is
|
|
705
|
+
* less than the overall length of the number, its fractional part is truncated through rounding.
|
|
706
|
+
* As the <code>precision</code> only affects the rounding of a number, its integer part can retain more digits
|
|
707
|
+
* than defined by this parameter.
|
|
708
|
+
* <b>Example:</b> With a <code>precision</code> of 2 and <code>style: "short"</code>,
|
|
709
|
+
* <code>234567</code> is formatted to <code>"235K"</code>.
|
|
710
|
+
* <b>Note:</b> The formatted output may differ depending on locale.
|
|
487
711
|
* @param {boolean} [oFormatOptions.preserveDecimals=false] Whether {@link #format} preserves
|
|
488
712
|
* decimal digits except trailing zeros in case there are more decimals than the
|
|
489
713
|
* <code>maxFractionDigits</code> format option allows.
|
|
490
714
|
* If decimals are not preserved, the formatted number is rounded to <code>maxFractionDigits</code>.
|
|
491
715
|
* @param {sap.ui.core.format.NumberFormat.RoundingMode} [oFormatOptions.roundingMode=TOWARDS_ZERO]
|
|
492
|
-
*
|
|
493
|
-
* defined by
|
|
716
|
+
* Specifies the rounding behavior for discarding the digits after the maximum fraction digits
|
|
717
|
+
* defined by <code>maxFractionDigits</code>.
|
|
494
718
|
* This can be assigned
|
|
495
719
|
* <ul>
|
|
496
720
|
* <li>by value in {@link sap.ui.core.format.NumberFormat.RoundingMode RoundingMode},</li>
|
|
497
|
-
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
721
|
+
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
722
|
+
* number of decimal digits that should be reserved. <b>Using a function is deprecated since 1.121.0</b>;
|
|
723
|
+
* string based numbers are not rounded via this custom function.</li>
|
|
498
724
|
* </ul>
|
|
499
725
|
* @param {int} [oFormatOptions.shortDecimals] defines the number of decimal in the shortened format string. If this isn't specified, the 'decimals' options is used
|
|
500
726
|
* @param {int} [oFormatOptions.shortLimit] only use short number formatting for values above this limit
|
|
@@ -508,24 +734,26 @@ NumberFormat.getFloatInstance = function (oFormatOptions, oLocale) {
|
|
|
508
734
|
* numbers are formatted into compact forms. When this option is set, the default value of the
|
|
509
735
|
* 'precision' option is set to 2. This can be changed by setting either min/maxFractionDigits,
|
|
510
736
|
* decimals, shortDecimals, or the 'precision' option itself.
|
|
511
|
-
* @param {sap.ui.core.Locale} [oLocale]
|
|
737
|
+
* @param {sap.ui.core.Locale} [oLocale]
|
|
738
|
+
* The locale to get the formatter for; if no locale is given, a locale for the currently configured language is
|
|
739
|
+
* used; see {@link module:sap/base/i18n/Formatting.getLanguageTag Formatting.getLanguageTag}
|
|
512
740
|
* @return {sap.ui.core.format.NumberFormat} integer instance of the NumberFormat
|
|
741
|
+
* @throws {Error} If the <code>oFormatOptions.decimalPadding</code> format option is provided
|
|
513
742
|
* @static
|
|
514
743
|
* @public
|
|
515
744
|
*/
|
|
516
745
|
NumberFormat.getIntegerInstance = function (oFormatOptions, oLocale) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
746
|
+
NumberFormat.checkDecimalPadding(oFormatOptions, false);
|
|
747
|
+
const oFormat = NumberFormat.createInstance(oFormatOptions, oLocale);
|
|
748
|
+
const oLocaleFormatOptions = oFormat.getLocaleFormatOptions(mNumberType.INTEGER);
|
|
749
|
+
oFormat.oFormatOptions = extend({}, NumberFormat.oDefaultIntegerFormat, oLocaleFormatOptions, oFormat.oOriginalFormatOptions);
|
|
750
|
+
oFormat.checkGroupingFormatOptions();
|
|
520
751
|
return oFormat;
|
|
521
752
|
};
|
|
522
753
|
|
|
523
754
|
/**
|
|
524
755
|
* Get a currency instance of the NumberFormat, which can be used for formatting.
|
|
525
756
|
*
|
|
526
|
-
* If no locale is given, the currently configured
|
|
527
|
-
* {@link sap.ui.core.Configuration.FormatSettings#getFormatLocale formatLocale} will be used.
|
|
528
|
-
*
|
|
529
757
|
* <p>
|
|
530
758
|
* This instance has HALF_AWAY_FROM_ZERO set as default rounding mode.
|
|
531
759
|
* Please set the roundingMode property in oFormatOptions to change the
|
|
@@ -550,7 +778,9 @@ NumberFormat.getIntegerInstance = function (oFormatOptions, oLocale) {
|
|
|
550
778
|
*
|
|
551
779
|
* As an alternative to using a fixed <code>symbol</code> for your custom currencies, you can also provide an ISO-Code.
|
|
552
780
|
* The provided ISO-Code will be used to look up the currency symbol in the global configuration,
|
|
553
|
-
* either defined in the CLDR or custom defined on the Format Settings (see
|
|
781
|
+
* either defined in the CLDR or custom defined on the Format Settings (see
|
|
782
|
+
* {@link module:sap/base/i18n/Formatting.setCustomCurrencies Formatting.setCustomCurrencies},
|
|
783
|
+
* {@link module:sap/base/i18n/Formatting.addCustomCurrencies Formatting.addCustomCurrencies}).
|
|
554
784
|
*
|
|
555
785
|
* If no symbol is given at all, the custom currency key is used for formatting.
|
|
556
786
|
*
|
|
@@ -587,7 +817,19 @@ NumberFormat.getIntegerInstance = function (oFormatOptions, oLocale) {
|
|
|
587
817
|
* If custom currencies are defined on the instance, no other currencies can be formatted and parsed by this instance.
|
|
588
818
|
* Globally available custom currencies can be added via the global configuration.
|
|
589
819
|
* See the above examples.
|
|
590
|
-
* See also {@link sap.
|
|
820
|
+
* See also {@link module:sap/base/i18n/Formatting.setCustomCurrencies Formatting.setCustomCurrencies} and
|
|
821
|
+
* {@link module:sap/base/i18n/Formatting.addCustomCurrencies Formatting.addCustomCurrencies}.
|
|
822
|
+
* @param {int} [oFormatOptions.decimalPadding]
|
|
823
|
+
* The target length of places after the decimal separator; if the number has fewer decimal places than given in
|
|
824
|
+
* this option, it is padded with whitespaces at the end up to the target length. An additional whitespace
|
|
825
|
+
* character for the decimal separator is added for a number without any decimals.
|
|
826
|
+
* <b>Note:</b> This format option is only allowed if the following conditions apply:
|
|
827
|
+
* <ul>
|
|
828
|
+
* <li>It has a value greater than 0.</li>
|
|
829
|
+
* <li>The <code>FormatOptions.showMeasure</code> format option is set to <code>false</code>.</li>
|
|
830
|
+
* <li>The <code>oFormatOptions.style</code> format option is <b>not</b> set to <code>"short"</code> or
|
|
831
|
+
* <code>"long"</code>.</li>
|
|
832
|
+
* </ul>
|
|
591
833
|
* @param {int} [oFormatOptions.decimals] defines the number of decimal digits
|
|
592
834
|
* @param {string} [oFormatOptions.decimalSeparator] defines the character used as decimal separator.
|
|
593
835
|
* Note: <code>decimalSeparator</code> must always be different from <code>groupingSeparator</code>.
|
|
@@ -600,15 +842,20 @@ NumberFormat.getIntegerInstance = function (oFormatOptions, oLocale) {
|
|
|
600
842
|
* @param {int} [oFormatOptions.groupingBaseSize=3] defines the grouping base size in digits if
|
|
601
843
|
* it is different from the grouping size (e.g. Indian grouping)
|
|
602
844
|
* @param {boolean} [oFormatOptions.groupingEnabled=true] defines whether grouping is enabled
|
|
603
|
-
* (grouping separators are shown)
|
|
845
|
+
* (grouping separators are shown).
|
|
846
|
+
* <b>Note:</b> Grouping is disabled if the <code>groupingSize</code> format option is set to
|
|
847
|
+
* a non-positive value.
|
|
604
848
|
* @param {string} [oFormatOptions.groupingSeparator] defines the character used as grouping separator.
|
|
605
849
|
* Note: <code>groupingSeparator</code> must always be different from <code>decimalSeparator</code>.
|
|
606
850
|
* @param {int} [oFormatOptions.groupingSize=3] defines the grouping size in digits; the default
|
|
607
|
-
* is <code>3</code>.
|
|
851
|
+
* is <code>3</code>.
|
|
852
|
+
* <b>Note:</b> If this format option is set to a non-positive value, grouping will be disabled entirely.
|
|
608
853
|
* @param {int} [oFormatOptions.maxFractionDigits=99] defines the maximum number of decimal digits
|
|
609
854
|
* @param {int} [oFormatOptions.maxIntegerDigits=99] defines the maximum number of non-decimal digits.
|
|
610
855
|
* If the number exceeds this maximum, e.g. 1e+120, "?" characters are shown instead of digits.
|
|
611
|
-
* @param {int} [oFormatOptions.minFractionDigits=0]
|
|
856
|
+
* @param {int} [oFormatOptions.minFractionDigits=0] Deprecated as of 1.130; this format option does not have
|
|
857
|
+
* an effect on currency formats since decimals can always be determined, either through the given format options,
|
|
858
|
+
* custom currencies or the CLDR
|
|
612
859
|
* @param {int} [oFormatOptions.minIntegerDigits=1] defines the minimal number of non-decimal digits
|
|
613
860
|
* @param {string} [oFormatOptions.minusSign] defines the used minus symbol
|
|
614
861
|
* @param {boolean} [oFormatOptions.parseAsString=false] since 1.28.2 defines whether to output
|
|
@@ -622,12 +869,14 @@ NumberFormat.getIntegerInstance = function (oFormatOptions, oLocale) {
|
|
|
622
869
|
* <code>maxFractionDigits</code> format option allows.
|
|
623
870
|
* If decimals are not preserved, the formatted number is rounded to <code>maxFractionDigits</code>.
|
|
624
871
|
* @param {sap.ui.core.format.NumberFormat.RoundingMode} [oFormatOptions.roundingMode=HALF_AWAY_FROM_ZERO]
|
|
625
|
-
*
|
|
626
|
-
* defined by
|
|
872
|
+
* Specifies the rounding behavior for discarding the digits after the maximum fraction digits
|
|
873
|
+
* defined by <code>maxFractionDigits</code>.
|
|
627
874
|
* This can be assigned
|
|
628
875
|
* <ul>
|
|
629
876
|
* <li>by value in {@link sap.ui.core.format.NumberFormat.RoundingMode RoundingMode},</li>
|
|
630
|
-
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
877
|
+
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
878
|
+
* number of decimal digits that should be reserved. <b>Using a function is deprecated since 1.121.0</b>;
|
|
879
|
+
* string based numbers are not rounded via this custom function.</li>
|
|
631
880
|
* </ul>
|
|
632
881
|
* @param {int} [oFormatOptions.shortDecimals] defines the number of decimal in the shortened format string. If this isn't specified, the 'decimals' options is used
|
|
633
882
|
* @param {int} [oFormatOptions.shortLimit] only use short number formatting for values above this limit
|
|
@@ -647,54 +896,48 @@ NumberFormat.getIntegerInstance = function (oFormatOptions, oLocale) {
|
|
|
647
896
|
* @param {boolean} [oFormatOptions.strictGroupingValidation=false] whether the positions of grouping separators are validated. Space characters used as grouping separators are not validated.
|
|
648
897
|
* @param {string} [oFormatOptions.style=standard] defines the style of format. Valid values are
|
|
649
898
|
* 'short, 'long' or 'standard' (based on the CLDR decimalFormat). When set to 'short' or 'long',
|
|
650
|
-
* numbers are formatted into
|
|
899
|
+
* numbers are formatted into the 'short' form only. When this option is set, the default value of the
|
|
651
900
|
* 'precision' option is set to 2. This can be changed by setting either min/maxFractionDigits,
|
|
652
901
|
* decimals, shortDecimals, or the 'precision' option itself.
|
|
653
902
|
* @param {boolean} [oFormatOptions.trailingCurrencyCode] overrides the global configuration
|
|
654
|
-
* value {@link sap.
|
|
655
|
-
* default value of <code>true</>.
|
|
903
|
+
* value {@link module:sap/base/i18n/Formatting.getTrailingCurrencyCode Formatting.getTrailingCurrencyCode},
|
|
904
|
+
* which has a default value of <code>true</>.
|
|
656
905
|
* This is ignored if <code>oFormatOptions.currencyCode</code> is set to <code>false</code>,
|
|
657
906
|
* or if <code>oFormatOptions.pattern</code> is supplied.
|
|
658
|
-
* @param {sap.ui.core.Locale} [oLocale]
|
|
907
|
+
* @param {sap.ui.core.Locale} [oLocale]
|
|
908
|
+
* The locale to get the formatter for; if no locale is given, a locale for the currently configured language is
|
|
909
|
+
* used; see {@link module:sap/base/i18n/Formatting.getLanguageTag Formatting.getLanguageTag}
|
|
659
910
|
* @return {sap.ui.core.format.NumberFormat} currency instance of the NumberFormat
|
|
911
|
+
* @throws {Error} If the <code>oFormatOptions.decimalPadding</code> is set but is not allowed
|
|
660
912
|
* @static
|
|
661
913
|
* @public
|
|
662
914
|
*/
|
|
663
915
|
NumberFormat.getCurrencyInstance = function (oFormatOptions, oLocale) {
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
var bShowTrailingCurrencyCode = showTrailingCurrencyCode(oFormat.oOriginalFormatOptions);
|
|
916
|
+
NumberFormat.checkDecimalPadding(oFormatOptions, true, true);
|
|
917
|
+
const oFormat = NumberFormat.createInstance(oFormatOptions, oLocale);
|
|
918
|
+
const oLocaleFormatOptions = oFormat.getLocaleFormatOptions(mNumberType.CURRENCY);
|
|
919
|
+
oFormat.oFormatOptions = extend({}, NumberFormat.oDefaultCurrencyFormat, oLocaleFormatOptions, oFormat.oOriginalFormatOptions);
|
|
669
920
|
|
|
670
|
-
//
|
|
671
|
-
|
|
672
|
-
sContext = sContext || this.oDefaultCurrencyFormat.style;
|
|
673
|
-
sContext = "sap-" + sContext;
|
|
674
|
-
}
|
|
675
|
-
var oLocaleFormatOptions = this.getLocaleFormatOptions(oFormat.oLocaleData, mNumberType.CURRENCY, sContext);
|
|
676
|
-
oFormat.oFormatOptions = extend({}, this.oDefaultCurrencyFormat, oLocaleFormatOptions, oFormat.oOriginalFormatOptions);
|
|
677
|
-
|
|
678
|
-
// Trailing currency code option
|
|
679
|
-
//
|
|
680
|
-
// The format option "trailingCurrencyCode" is influenced by other options, such as pattern, currencyCode, global config
|
|
921
|
+
// The format option "trailingCurrencyCode" is influenced by other options, such as pattern, currencyCode,
|
|
922
|
+
// global config
|
|
681
923
|
// Therefore set it manually without modifying the original oFormatOptions.
|
|
682
924
|
// E.g. the "pattern" option would overwrite this option, even if the "trailingCurrencyCode" option is set
|
|
683
925
|
// oFormatOptions.pattern = "###"
|
|
684
926
|
// oFormatOptions.trailingCurrencyCode = true
|
|
685
927
|
// ->
|
|
686
928
|
// oFormatOptions.trailingCurrencyCode = false
|
|
687
|
-
oFormat.oFormatOptions.trailingCurrencyCode =
|
|
929
|
+
oFormat.oFormatOptions.trailingCurrencyCode = oFormat.showTrailingCurrencyCode();
|
|
688
930
|
oFormat._defineCustomCurrencySymbols();
|
|
931
|
+
if (oFormat.oFormatOptions.style === "long") {
|
|
932
|
+
oFormat.oFormatOptions.style = "short";
|
|
933
|
+
}
|
|
934
|
+
oFormat.checkGroupingFormatOptions();
|
|
689
935
|
return oFormat;
|
|
690
936
|
};
|
|
691
937
|
|
|
692
938
|
/**
|
|
693
939
|
* Get a unit instance of the NumberFormat, which can be used for formatting units.
|
|
694
940
|
*
|
|
695
|
-
* If no locale is given, the currently configured
|
|
696
|
-
* {@link sap.ui.core.Configuration.FormatSettings#getFormatLocale formatLocale} will be used.
|
|
697
|
-
*
|
|
698
941
|
* <p>
|
|
699
942
|
* This instance has HALF_AWAY_FROM_ZERO set as default rounding mode.
|
|
700
943
|
* Please set the roundingMode property in oFormatOptions to change the
|
|
@@ -713,6 +956,17 @@ NumberFormat.getCurrencyInstance = function (oFormatOptions, oLocale) {
|
|
|
713
956
|
* "decimals": 2,
|
|
714
957
|
* "precision": 4
|
|
715
958
|
* }}
|
|
959
|
+
* @param {int} [oFormatOptions.decimalPadding]
|
|
960
|
+
* The target length of places after the decimal separator; if the number has fewer decimal places than given in
|
|
961
|
+
* this option, it is padded with whitespaces at the end up to the target length. An additional whitespace
|
|
962
|
+
* character for the decimal separator is added for a number without any decimals.
|
|
963
|
+
* <b>Note:</b> This format option is only allowed if the following conditions apply:
|
|
964
|
+
* <ul>
|
|
965
|
+
* <li>It has a value greater than 0.</li>
|
|
966
|
+
* <li>The <code>FormatOptions.showMeasure</code> format option is set to <code>false</code>.</li>
|
|
967
|
+
* <li>The <code>oFormatOptions.style</code> format option is <b>not</b> set to <code>"short"</code> or
|
|
968
|
+
* <code>"long"</code>.</li>
|
|
969
|
+
* </ul>
|
|
716
970
|
* @param {int} [oFormatOptions.decimals] defines the number of decimal digits
|
|
717
971
|
* @param {string} [oFormatOptions.decimalSeparator] defines the character used as decimal separator.
|
|
718
972
|
* Note: <code>decimalSeparator</code> must always be different from <code>groupingSeparator</code>.
|
|
@@ -725,11 +979,14 @@ NumberFormat.getCurrencyInstance = function (oFormatOptions, oLocale) {
|
|
|
725
979
|
* @param {int} [oFormatOptions.groupingBaseSize=3] defines the grouping base size in digits if
|
|
726
980
|
* it is different from the grouping size (e.g. Indian grouping)
|
|
727
981
|
* @param {boolean} [oFormatOptions.groupingEnabled=true] defines whether grouping is enabled
|
|
728
|
-
* (grouping separators are shown)
|
|
982
|
+
* (grouping separators are shown).
|
|
983
|
+
* <b>Note:</b> Grouping is disabled if the <code>groupingSize</code> format option is set to
|
|
984
|
+
* a non-positive value.
|
|
729
985
|
* @param {string} [oFormatOptions.groupingSeparator] defines the character used as grouping separator.
|
|
730
986
|
* Note: <code>groupingSeparator</code> must always be different from <code>decimalSeparator</code>.
|
|
731
987
|
* @param {int} [oFormatOptions.groupingSize=3] defines the grouping size in digits; the default
|
|
732
|
-
* is <code>3</code>.
|
|
988
|
+
* is <code>3</code>.
|
|
989
|
+
* <b>Note:</b> If this format option is set to a non-positive value, grouping will be disabled entirely.
|
|
733
990
|
* @param {int} [oFormatOptions.maxFractionDigits=99] defines the maximum number of decimal digits
|
|
734
991
|
* @param {int} [oFormatOptions.maxIntegerDigits=99] defines the maximum number of non-decimal digits.
|
|
735
992
|
* If the number exceeds this maximum, e.g. 1e+120, "?" characters are shown instead of digits.
|
|
@@ -742,19 +999,26 @@ NumberFormat.getCurrencyInstance = function (oFormatOptions, oLocale) {
|
|
|
742
999
|
* to "0.005".
|
|
743
1000
|
* @param {string} [oFormatOptions.pattern] CLDR number pattern which is used to format the number
|
|
744
1001
|
* @param {string} [oFormatOptions.plusSign] defines the used plus symbol
|
|
745
|
-
* @param {int} [oFormatOptions.precision]
|
|
746
|
-
* is
|
|
1002
|
+
* @param {int} [oFormatOptions.precision] The maximum number of digits in the formatted representation of a number;
|
|
1003
|
+
* if the <code>precision</code> is less than the overall length of the number, its fractional part is truncated
|
|
1004
|
+
* through rounding. As the <code>precision</code> only affects the rounding of a number, its integer part can
|
|
1005
|
+
* retain more digits than defined by this parameter.
|
|
1006
|
+
* <b>Example:</b> With a <code>precision</code> of 2, the parameters <code>"234.567", "mass-kilogram"</code> are
|
|
1007
|
+
* formatted to <code>"235 kg"</code>.
|
|
1008
|
+
* <b>Note:</b> The formatted output may differ depending on locale.
|
|
747
1009
|
* @param {boolean} [oFormatOptions.preserveDecimals=false] Whether {@link #format} preserves
|
|
748
1010
|
* decimal digits except trailing zeros in case there are more decimals than the
|
|
749
1011
|
* <code>maxFractionDigits</code> format option allows.
|
|
750
1012
|
* If decimals are not preserved, the formatted number is rounded to <code>maxFractionDigits</code>.
|
|
751
1013
|
* @param {sap.ui.core.format.NumberFormat.RoundingMode} [oFormatOptions.roundingMode=HALF_AWAY_FROM_ZERO]
|
|
752
|
-
*
|
|
753
|
-
* defined by
|
|
1014
|
+
* Specifies the rounding behavior for discarding the digits after the maximum fraction digits
|
|
1015
|
+
* defined by <code>maxFractionDigits</code>.
|
|
754
1016
|
* This can be assigned
|
|
755
1017
|
* <ul>
|
|
756
1018
|
* <li>by value in {@link sap.ui.core.format.NumberFormat.RoundingMode RoundingMode},</li>
|
|
757
|
-
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
1019
|
+
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
1020
|
+
* number of decimal digits that should be reserved. <b>Using a function is deprecated since 1.121.0</b>;
|
|
1021
|
+
* string based numbers are not rounded via this custom function.</li>
|
|
758
1022
|
* </ul>
|
|
759
1023
|
* @param {int} [oFormatOptions.shortDecimals] defines the number of decimals in the shortened
|
|
760
1024
|
* format string. If this option isn't specified, the 'decimals' option is used instead.
|
|
@@ -783,24 +1047,26 @@ NumberFormat.getCurrencyInstance = function (oFormatOptions, oLocale) {
|
|
|
783
1047
|
* numbers are formatted into compact forms. When this option is set, the default value of the
|
|
784
1048
|
* 'precision' option is set to 2. This can be changed by setting either min/maxFractionDigits,
|
|
785
1049
|
* decimals, shortDecimals, or the 'precision' option itself.
|
|
786
|
-
* @param {sap.ui.core.Locale} [oLocale]
|
|
1050
|
+
* @param {sap.ui.core.Locale} [oLocale]
|
|
1051
|
+
* The locale to get the formatter for; if no locale is given, a locale for the currently configured language is
|
|
1052
|
+
* used; see {@link module:sap/base/i18n/Formatting.getLanguageTag Formatting.getLanguageTag}
|
|
787
1053
|
* @return {sap.ui.core.format.NumberFormat} unit instance of the NumberFormat
|
|
1054
|
+
* @throws {Error} If the <code>oFormatOptions.decimalPadding</code> is set but is not allowed
|
|
788
1055
|
* @static
|
|
789
1056
|
* @public
|
|
790
1057
|
*/
|
|
791
1058
|
NumberFormat.getUnitInstance = function (oFormatOptions, oLocale) {
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1059
|
+
NumberFormat.checkDecimalPadding(oFormatOptions, true, true);
|
|
1060
|
+
const oFormat = NumberFormat.createInstance(oFormatOptions, oLocale);
|
|
1061
|
+
const oLocaleFormatOptions = oFormat.getLocaleFormatOptions(mNumberType.UNIT);
|
|
1062
|
+
oFormat.oFormatOptions = extend({}, NumberFormat.oDefaultUnitFormat, oLocaleFormatOptions, oFormat.oOriginalFormatOptions);
|
|
1063
|
+
oFormat.checkGroupingFormatOptions();
|
|
795
1064
|
return oFormat;
|
|
796
1065
|
};
|
|
797
1066
|
|
|
798
1067
|
/**
|
|
799
1068
|
* Get a percent instance of the NumberFormat, which can be used for formatting.
|
|
800
1069
|
*
|
|
801
|
-
* If no locale is given, the currently configured
|
|
802
|
-
* {@link sap.ui.core.Configuration.FormatSettings#getFormatLocale formatLocale} will be used.
|
|
803
|
-
*
|
|
804
1070
|
* <p>
|
|
805
1071
|
* This instance has HALF_AWAY_FROM_ZERO set as default rounding mode.
|
|
806
1072
|
* Please set the roundingMode property in oFormatOptions to change the
|
|
@@ -809,6 +1075,7 @@ NumberFormat.getUnitInstance = function (oFormatOptions, oLocale) {
|
|
|
809
1075
|
*
|
|
810
1076
|
* @param {object} [oFormatOptions] The option object, which supports the following parameters.
|
|
811
1077
|
* If no options are given, default values according to the type and locale settings are used.
|
|
1078
|
+
* @param {int} [oFormatOptions.decimalPadding] Not supported.
|
|
812
1079
|
* @param {int} [oFormatOptions.decimals] defines the number of decimal digits
|
|
813
1080
|
* @param {string} [oFormatOptions.decimalSeparator] defines the character used as decimal separator.
|
|
814
1081
|
* Note: <code>decimalSeparator</code> must always be different from <code>groupingSeparator</code>.
|
|
@@ -821,11 +1088,14 @@ NumberFormat.getUnitInstance = function (oFormatOptions, oLocale) {
|
|
|
821
1088
|
* @param {int} [oFormatOptions.groupingBaseSize=3] defines the grouping base size in digits if
|
|
822
1089
|
* it is different from the grouping size (e.g. Indian grouping)
|
|
823
1090
|
* @param {boolean} [oFormatOptions.groupingEnabled=true] defines whether grouping is enabled
|
|
824
|
-
* (grouping separators are shown)
|
|
1091
|
+
* (grouping separators are shown).
|
|
1092
|
+
* <b>Note:</b> Grouping is disabled if the <code>groupingSize</code> format option is set to
|
|
1093
|
+
* a non-positive value.
|
|
825
1094
|
* @param {string} [oFormatOptions.groupingSeparator] defines the character used as grouping separator.
|
|
826
1095
|
* Note: <code>groupingSeparator</code> must always be different from <code>decimalSeparator</code>.
|
|
827
1096
|
* @param {int} [oFormatOptions.groupingSize=3] defines the grouping size in digits; the default
|
|
828
|
-
* is <code>3</code>.
|
|
1097
|
+
* is <code>3</code>.
|
|
1098
|
+
* <b>Note:</b> If this format option is set to a non-positive value, grouping will be disabled entirely.
|
|
829
1099
|
* @param {int} [oFormatOptions.maxFractionDigits=99] defines the maximum number of decimal digits
|
|
830
1100
|
* @param {int} [oFormatOptions.maxIntegerDigits=99] defines the maximum number of non-decimal digits.
|
|
831
1101
|
* If the number exceeds this maximum, e.g. 1e+120, "?" characters are shown instead of digits.
|
|
@@ -839,19 +1109,26 @@ NumberFormat.getUnitInstance = function (oFormatOptions, oLocale) {
|
|
|
839
1109
|
* @param {string} [oFormatOptions.pattern] CLDR number pattern which is used to format the number
|
|
840
1110
|
* @param {string} [oFormatOptions.percentSign] defines the used percent symbol
|
|
841
1111
|
* @param {string} [oFormatOptions.plusSign] defines the used plus symbol
|
|
842
|
-
* @param {int} [oFormatOptions.precision]
|
|
843
|
-
* is
|
|
1112
|
+
* @param {int} [oFormatOptions.precision] The maximum number of digits in the formatted representation of a number;
|
|
1113
|
+
* if the <code>precision</code> is less than the overall length of the number, its fractional part is truncated
|
|
1114
|
+
* through rounding. As the <code>precision</code> only affects the rounding of a number, its integer part
|
|
1115
|
+
* can retain more digits than defined by this parameter.
|
|
1116
|
+
* <b>Example:</b> With a <code>precision</code> of 2, <code>234.567</code> is formatted to
|
|
1117
|
+
* <code>"23,457%"</code>.
|
|
1118
|
+
* <b>Note:</b> The formatted output may differ depending on locale.
|
|
844
1119
|
* @param {boolean} [oFormatOptions.preserveDecimals=false] Whether {@link #format} preserves
|
|
845
1120
|
* decimal digits except trailing zeros in case there are more decimals than the
|
|
846
1121
|
* <code>maxFractionDigits</code> format option allows.
|
|
847
1122
|
* If decimals are not preserved, the formatted number is rounded to <code>maxFractionDigits</code>.
|
|
848
1123
|
* @param {sap.ui.core.format.NumberFormat.RoundingMode} [oFormatOptions.roundingMode=HALF_AWAY_FROM_ZERO]
|
|
849
|
-
*
|
|
850
|
-
* defined by
|
|
1124
|
+
* Specifies the rounding behavior for discarding the digits after the maximum fraction digits
|
|
1125
|
+
* defined by <code>maxFractionDigits</code>.
|
|
851
1126
|
* This can be assigned
|
|
852
1127
|
* <ul>
|
|
853
1128
|
* <li>by value in {@link sap.ui.core.format.NumberFormat.RoundingMode RoundingMode},</li>
|
|
854
|
-
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
1129
|
+
* <li>via a function that is used for rounding the number and takes two parameters: the number itself, and the
|
|
1130
|
+
* number of decimal digits that should be reserved. <b>Using a function is deprecated since 1.121.0</b>;
|
|
1131
|
+
* string based numbers are not rounded via this custom function.</li>
|
|
855
1132
|
* </ul>
|
|
856
1133
|
* @param {int} [oFormatOptions.shortDecimals] defines the number of decimal in the shortened format string. If this isn't specified, the 'decimals' options is used
|
|
857
1134
|
* @param {int} [oFormatOptions.shortLimit] only use short number formatting for values above this limit
|
|
@@ -865,15 +1142,20 @@ NumberFormat.getUnitInstance = function (oFormatOptions, oLocale) {
|
|
|
865
1142
|
* numbers are formatted into compact forms. When this option is set, the default value of the
|
|
866
1143
|
* 'precision' option is set to 2. This can be changed by setting either min/maxFractionDigits,
|
|
867
1144
|
* decimals, shortDecimals, or the 'precision' option itself.
|
|
868
|
-
* @param {sap.ui.core.Locale} [oLocale]
|
|
1145
|
+
* @param {sap.ui.core.Locale} [oLocale]
|
|
1146
|
+
* The locale to get the formatter for; if no locale is given, a locale for the currently configured language is
|
|
1147
|
+
* used; see {@link module:sap/base/i18n/Formatting.getLanguageTag Formatting.getLanguageTag}
|
|
869
1148
|
* @return {sap.ui.core.format.NumberFormat} percentage instance of the NumberFormat
|
|
1149
|
+
* @throws {Error} If the <code>oFormatOptions.decimalPadding</code> format option is provided
|
|
870
1150
|
* @static
|
|
871
1151
|
* @public
|
|
872
1152
|
*/
|
|
873
1153
|
NumberFormat.getPercentInstance = function (oFormatOptions, oLocale) {
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
1154
|
+
NumberFormat.checkDecimalPadding(oFormatOptions, false);
|
|
1155
|
+
const oFormat = NumberFormat.createInstance(oFormatOptions, oLocale);
|
|
1156
|
+
const oLocaleFormatOptions = oFormat.getLocaleFormatOptions(mNumberType.PERCENT);
|
|
1157
|
+
oFormat.oFormatOptions = extend({}, NumberFormat.oDefaultPercentFormat, oLocaleFormatOptions, oFormat.oOriginalFormatOptions);
|
|
1158
|
+
oFormat.checkGroupingFormatOptions();
|
|
877
1159
|
return oFormat;
|
|
878
1160
|
};
|
|
879
1161
|
|
|
@@ -893,7 +1175,7 @@ NumberFormat.createInstance = function (oFormatOptions, oLocale) {
|
|
|
893
1175
|
oFormatOptions = undefined;
|
|
894
1176
|
}
|
|
895
1177
|
if (!oLocale) {
|
|
896
|
-
oLocale =
|
|
1178
|
+
oLocale = new Locale(Formatting.getLanguageTag());
|
|
897
1179
|
}
|
|
898
1180
|
oFormat.oLocale = oLocale;
|
|
899
1181
|
oFormat.oLocaleData = LocaleData.getInstance(oLocale);
|
|
@@ -939,30 +1221,38 @@ NumberFormat.createInstance = function (oFormatOptions, oLocale) {
|
|
|
939
1221
|
* @ui5-restricted sap.ui.model.odata.type
|
|
940
1222
|
*/
|
|
941
1223
|
NumberFormat.getDefaultUnitPattern = function (sShortName) {
|
|
942
|
-
return "{0}
|
|
1224
|
+
return "{0}\u00a0" + sShortName;
|
|
943
1225
|
};
|
|
944
1226
|
|
|
945
1227
|
/**
|
|
946
|
-
*
|
|
1228
|
+
* Gets the default locale-dependent format options for the given number format type.
|
|
947
1229
|
*
|
|
948
|
-
* @
|
|
1230
|
+
* @param {"integer"|"float"|"currency"|"unit"|"percent"} sType
|
|
1231
|
+
* The number format type
|
|
1232
|
+
* @returns {object} The default locale-dependent format options for the given number format type
|
|
1233
|
+
*
|
|
1234
|
+
* @private
|
|
949
1235
|
*/
|
|
950
|
-
NumberFormat.getLocaleFormatOptions = function (
|
|
951
|
-
|
|
952
|
-
|
|
1236
|
+
NumberFormat.prototype.getLocaleFormatOptions = function (sType) {
|
|
1237
|
+
const oLocaleData = this.oLocaleData;
|
|
1238
|
+
let sNumberPattern;
|
|
1239
|
+
let sContext;
|
|
1240
|
+
switch (sType) {
|
|
953
1241
|
case mNumberType.PERCENT:
|
|
954
1242
|
sNumberPattern = oLocaleData.getPercentPattern();
|
|
955
1243
|
break;
|
|
956
1244
|
case mNumberType.CURRENCY:
|
|
1245
|
+
sContext = this.oOriginalFormatOptions?.currencyContext || NumberFormat.oDefaultCurrencyFormat.style;
|
|
1246
|
+
// prepend "sap-" to pattern params to load (context and short)
|
|
1247
|
+
if (this.showTrailingCurrencyCode()) {
|
|
1248
|
+
sContext = "sap-" + sContext;
|
|
1249
|
+
}
|
|
957
1250
|
sNumberPattern = oLocaleData.getCurrencyPattern(sContext);
|
|
958
1251
|
break;
|
|
959
|
-
case mNumberType.UNIT:
|
|
960
|
-
sNumberPattern = oLocaleData.getDecimalPattern();
|
|
961
|
-
break;
|
|
962
1252
|
default:
|
|
963
1253
|
sNumberPattern = oLocaleData.getDecimalPattern();
|
|
964
1254
|
}
|
|
965
|
-
oLocaleFormatOptions =
|
|
1255
|
+
const oLocaleFormatOptions = NumberFormat.parseNumberPattern(sNumberPattern);
|
|
966
1256
|
oLocaleFormatOptions.plusSign = oLocaleData.getNumberSymbol("plusSign");
|
|
967
1257
|
oLocaleFormatOptions.minusSign = oLocaleData.getNumberSymbol("minusSign");
|
|
968
1258
|
oLocaleFormatOptions.decimalSeparator = oLocaleData.getNumberSymbol("decimal");
|
|
@@ -972,14 +1262,7 @@ NumberFormat.getLocaleFormatOptions = function (oLocaleData, iType, sContext) {
|
|
|
972
1262
|
|
|
973
1263
|
// Some options need to be overridden to stay compatible with the formatting defaults
|
|
974
1264
|
// before pattern parsing was added to the NumberFormat
|
|
975
|
-
switch (
|
|
976
|
-
case mNumberType.UNIT:
|
|
977
|
-
case mNumberType.FLOAT:
|
|
978
|
-
case mNumberType.PERCENT:
|
|
979
|
-
// Unlimited fraction digits for float and percent values
|
|
980
|
-
oLocaleFormatOptions.minFractionDigits = 0;
|
|
981
|
-
oLocaleFormatOptions.maxFractionDigits = 99;
|
|
982
|
-
break;
|
|
1265
|
+
switch (sType) {
|
|
983
1266
|
case mNumberType.INTEGER:
|
|
984
1267
|
// No fraction digits and no grouping for integer values
|
|
985
1268
|
oLocaleFormatOptions.minFractionDigits = 0;
|
|
@@ -991,6 +1274,11 @@ NumberFormat.getLocaleFormatOptions = function (oLocaleData, iType, sContext) {
|
|
|
991
1274
|
oLocaleFormatOptions.minFractionDigits = undefined;
|
|
992
1275
|
oLocaleFormatOptions.maxFractionDigits = undefined;
|
|
993
1276
|
break;
|
|
1277
|
+
default:
|
|
1278
|
+
// cases: mNumberType.UNIT, mNumberType.FLOAT and mNumberType.PERCENT
|
|
1279
|
+
// Unlimited fraction digits
|
|
1280
|
+
oLocaleFormatOptions.minFractionDigits = 0;
|
|
1281
|
+
oLocaleFormatOptions.maxFractionDigits = 99;
|
|
994
1282
|
}
|
|
995
1283
|
return oLocaleFormatOptions;
|
|
996
1284
|
};
|
|
@@ -1143,7 +1431,7 @@ NumberFormat.prototype._defineCustomCurrencySymbols = function () {
|
|
|
1143
1431
|
* @returns {string} the number with stripped trailing zero decimals, e.g. "1.230"
|
|
1144
1432
|
*/
|
|
1145
1433
|
function stripTrailingZeroDecimals(sNumber, minDecimalsPreserved) {
|
|
1146
|
-
if (sNumber.indexOf(".") >= 0 &&
|
|
1434
|
+
if (sNumber.indexOf(".") >= 0 && sNumber.endsWith("0")) {
|
|
1147
1435
|
var iFractionDigitsLength = sNumber.length - sNumber.lastIndexOf(".") - 1;
|
|
1148
1436
|
var iFractionsToRemove = iFractionDigitsLength - minDecimalsPreserved;
|
|
1149
1437
|
if (iFractionsToRemove > 0) {
|
|
@@ -1193,9 +1481,13 @@ function applyGrouping(sIntegerPart, oOptions) {
|
|
|
1193
1481
|
/**
|
|
1194
1482
|
* Format a number according to the given format options.
|
|
1195
1483
|
*
|
|
1196
|
-
* @param {number|array} vValue
|
|
1197
|
-
*
|
|
1198
|
-
*
|
|
1484
|
+
* @param {number|string|array} vValue
|
|
1485
|
+
* The number to format as a number or a string, such as <code>1234.45</code> or <code>"-1234.45"</code>, or an
|
|
1486
|
+
* array which contains both the number to format as a number or a string and the <code>sMeasure</code> parameter
|
|
1487
|
+
* @param {string} [sMeasure]
|
|
1488
|
+
* An optional unit which has an impact on formatting currencies and units
|
|
1489
|
+
* @returns {string}
|
|
1490
|
+
* The formatted value
|
|
1199
1491
|
* @public
|
|
1200
1492
|
*/
|
|
1201
1493
|
NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
@@ -1214,18 +1506,12 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1214
1506
|
oOptions = Object.assign({}, this.oFormatOptions),
|
|
1215
1507
|
oOrigOptions = this.oOriginalFormatOptions,
|
|
1216
1508
|
bIndianCurrency = oOptions.type === mNumberType.CURRENCY && sMeasure === "INR" && this.oLocale.getLanguage() === "en" && this.oLocale.getRegion() === "IN",
|
|
1217
|
-
aPatternParts,
|
|
1218
1509
|
oShortFormat,
|
|
1219
1510
|
nShortRefNumber,
|
|
1220
1511
|
sPluralCategory,
|
|
1221
1512
|
mUnitPatterns,
|
|
1222
1513
|
sLookupMeasure,
|
|
1223
1514
|
bValueIsNullOrUndefined = vValue === undefined || vValue === null;
|
|
1224
|
-
if (oOptions.groupingEnabled && oOptions.groupingSize <= 0) {
|
|
1225
|
-
// invalid grouping size specified
|
|
1226
|
-
Log.error("Grouping requires the 'groupingSize' format option to be a positive number, but it is '" + oOptions.groupingSize + "' instead.");
|
|
1227
|
-
return "";
|
|
1228
|
-
}
|
|
1229
1515
|
|
|
1230
1516
|
// emptyString is only relevant for the number part (vValue)
|
|
1231
1517
|
if (oOptions.showNumber && (vValue === oOptions.emptyString || isNaN(vValue) && isNaN(oOptions.emptyString))) {
|
|
@@ -1277,13 +1563,16 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1277
1563
|
if (!mUnitPatterns && !oOptions.showNumber) {
|
|
1278
1564
|
return this._addOriginInfo(sMeasure);
|
|
1279
1565
|
}
|
|
1280
|
-
|
|
1566
|
+
}
|
|
1567
|
+
if (oOptions.type === mNumberType.UNIT) {
|
|
1281
1568
|
// either take the decimals/precision on the custom units or fallback to the given format-options
|
|
1282
1569
|
oOptions.decimals = mUnitPatterns && typeof mUnitPatterns.decimals === "number" && mUnitPatterns.decimals >= 0 ? mUnitPatterns.decimals : oOptions.decimals;
|
|
1283
|
-
oOptions.decimals = NumberFormat.
|
|
1570
|
+
oOptions.decimals = NumberFormat.getMaximumDecimals(oOptions);
|
|
1284
1571
|
oOptions.precision = mUnitPatterns && typeof mUnitPatterns.precision === "number" && mUnitPatterns.precision >= 0 ? mUnitPatterns.precision : oOptions.precision;
|
|
1285
1572
|
}
|
|
1286
|
-
|
|
1573
|
+
let sCurrencySymbolOrCode;
|
|
1574
|
+
if (oOptions.type === mNumberType.CURRENCY) {
|
|
1575
|
+
sCurrencySymbolOrCode = this.getCurrencySymbolOrCode(sMeasure, oOptions.currencyCode);
|
|
1287
1576
|
// Make sure the "trailingCurrencyCode" mode is only used on currency codes:
|
|
1288
1577
|
// The "customCurrencies" format option takes precedence over CLDR and global configuration. If the given measure isn't found
|
|
1289
1578
|
// there, we already return an empty string in the check above (look for error log 'Currency "xy" is unknown').
|
|
@@ -1292,34 +1581,23 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1292
1581
|
// it shouldn't be formatted with the "trailingCurrencyCode" pattern.
|
|
1293
1582
|
if (sMeasure && oOptions.trailingCurrencyCode) {
|
|
1294
1583
|
if (!this.mKnownCurrencyCodes[sMeasure] && !/(^[A-Z]{3}$)/.test(sMeasure)) {
|
|
1295
|
-
oOptions.trailingCurrencyCode = false;
|
|
1296
1584
|
// Revert to non-"sap-" prefixed (trailing-currency-code) pattern. Also see code in getCurrencyInstance()
|
|
1297
|
-
oOptions.
|
|
1585
|
+
oOptions.trailingCurrencyCode = false;
|
|
1298
1586
|
}
|
|
1299
1587
|
}
|
|
1300
1588
|
if (!oOptions.showNumber) {
|
|
1301
1589
|
// if the number should not be shown, return the sMeasure part standalone, without anything number specific
|
|
1302
|
-
|
|
1303
|
-
var sSymbol;
|
|
1304
|
-
// custom currencies provided
|
|
1305
|
-
if (oOptions.customCurrencies && typeof oOptions.customCurrencies === "object") {
|
|
1306
|
-
// the custom currency symbol map was preprocessed on instance creation
|
|
1307
|
-
sSymbol = this.mKnownCurrencySymbols[sMeasure];
|
|
1308
|
-
} else {
|
|
1309
|
-
sSymbol = this.oLocaleData.getCurrencySymbol(sMeasure);
|
|
1310
|
-
}
|
|
1311
|
-
if (sSymbol && sSymbol !== sMeasure) {
|
|
1312
|
-
sMeasure = sSymbol;
|
|
1313
|
-
}
|
|
1314
|
-
}
|
|
1315
|
-
return sMeasure;
|
|
1590
|
+
return sCurrencySymbolOrCode;
|
|
1316
1591
|
}
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1592
|
+
if (oOptions.style === "long" || oOptions.style === "short") {
|
|
1593
|
+
oOptions.maxFractionDigits ??= 0;
|
|
1594
|
+
} else {
|
|
1595
|
+
if (oOptions.customCurrencies?.[sMeasure]?.decimals !== undefined) {
|
|
1596
|
+
oOptions.decimals = oOptions.customCurrencies[sMeasure].decimals;
|
|
1597
|
+
} else {
|
|
1598
|
+
oOptions.decimals ??= this.oLocaleData.getCurrencyDigits(sMeasure);
|
|
1599
|
+
}
|
|
1600
|
+
oOptions.decimals = NumberFormat.getMaximumDecimals(oOptions);
|
|
1323
1601
|
}
|
|
1324
1602
|
}
|
|
1325
1603
|
|
|
@@ -1330,7 +1608,7 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1330
1608
|
}
|
|
1331
1609
|
if (oOptions.shortLimit === undefined || Math.abs(vValue) >= oOptions.shortLimit) {
|
|
1332
1610
|
nShortRefNumber = oOptions.shortRefNumber === undefined ? vValue : oOptions.shortRefNumber;
|
|
1333
|
-
oShortFormat = getShortenedFormat(nShortRefNumber, oOptions,
|
|
1611
|
+
oShortFormat = this.getShortenedFormat(nShortRefNumber, oOptions, bIndianCurrency);
|
|
1334
1612
|
if (oShortFormat && oShortFormat.formatString != "0") {
|
|
1335
1613
|
vValue = vValue / oShortFormat.magnitude;
|
|
1336
1614
|
// If shortDecimals is defined, override the fractionDigits
|
|
@@ -1373,28 +1651,12 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1373
1651
|
vValue = NumberFormat._shiftDecimalPoint(vValue, 2);
|
|
1374
1652
|
}
|
|
1375
1653
|
|
|
1376
|
-
//handle measure
|
|
1377
|
-
if (oOptions.type == mNumberType.CURRENCY) {
|
|
1378
|
-
var iDigits = this.oLocaleData.getCurrencyDigits(sMeasure);
|
|
1379
|
-
|
|
1380
|
-
// decimals might be undefined, yet 0 is accepted of course
|
|
1381
|
-
if (oOptions.customCurrencies && oOptions.customCurrencies[sMeasure] && oOptions.customCurrencies[sMeasure].decimals !== undefined) {
|
|
1382
|
-
iDigits = oOptions.customCurrencies[sMeasure].decimals;
|
|
1383
|
-
}
|
|
1384
|
-
if (oOptions.maxFractionDigits === undefined) {
|
|
1385
|
-
oOptions.maxFractionDigits = iDigits;
|
|
1386
|
-
}
|
|
1387
|
-
if (oOptions.minFractionDigits === undefined) {
|
|
1388
|
-
oOptions.minFractionDigits = iDigits;
|
|
1389
|
-
}
|
|
1390
|
-
}
|
|
1391
|
-
|
|
1392
1654
|
// Rounding the value with oOptions.maxFractionDigits and oOptions.roundingMode.
|
|
1393
1655
|
//
|
|
1394
1656
|
// If the number of fraction digits are equal or less than oOptions.maxFractionDigits, the
|
|
1395
1657
|
// number isn't changed. After this operation, the number of fraction digits is
|
|
1396
1658
|
// equal or less than oOptions.maxFractionDigits.
|
|
1397
|
-
if (typeof vValue === "number" && !oOptions.preserveDecimals) {
|
|
1659
|
+
if ((typeof vValue === "number" || typeof vValue === "string" && typeof oOptions.roundingMode !== "function") && !oOptions.preserveDecimals) {
|
|
1398
1660
|
vValue = rounding(vValue, oOptions.maxFractionDigits, oOptions.roundingMode);
|
|
1399
1661
|
}
|
|
1400
1662
|
|
|
@@ -1402,6 +1664,12 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1402
1664
|
if (vValue == 0) {
|
|
1403
1665
|
bNegative = false;
|
|
1404
1666
|
}
|
|
1667
|
+
if (!bValueIsNullOrUndefined) {
|
|
1668
|
+
sNumber = LocaleData.convertToDecimal(vValue);
|
|
1669
|
+
}
|
|
1670
|
+
if (sNumber === "NaN") {
|
|
1671
|
+
return sNumber;
|
|
1672
|
+
}
|
|
1405
1673
|
|
|
1406
1674
|
// strip of trailing zeros in decimals
|
|
1407
1675
|
// "1000.00" -> "1000" (maxFractionDigits: 0)
|
|
@@ -1411,14 +1679,8 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1411
1679
|
// These zeros are cut off until maxFractionDigits is reached to be backward compatible.
|
|
1412
1680
|
// If more trailing decimal zeros are required the option maxFractionDigits can be increased.
|
|
1413
1681
|
// Note: default maxFractionDigits for Unit and Float is 99.
|
|
1414
|
-
if (oOptions.preserveDecimals
|
|
1415
|
-
|
|
1416
|
-
}
|
|
1417
|
-
if (!bValueIsNullOrUndefined) {
|
|
1418
|
-
sNumber = LocaleData.convertToDecimal(vValue);
|
|
1419
|
-
}
|
|
1420
|
-
if (sNumber == "NaN") {
|
|
1421
|
-
return sNumber;
|
|
1682
|
+
if (oOptions.preserveDecimals) {
|
|
1683
|
+
sNumber = stripTrailingZeroDecimals(sNumber, oOptions.maxFractionDigits);
|
|
1422
1684
|
}
|
|
1423
1685
|
|
|
1424
1686
|
// if number is negative remove minus
|
|
@@ -1485,7 +1747,10 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1485
1747
|
} else {
|
|
1486
1748
|
sGroupedIntegerPart = sIntegerPart;
|
|
1487
1749
|
}
|
|
1488
|
-
|
|
1750
|
+
const iDecimalPadding = oOptions.decimalPadding || 0;
|
|
1751
|
+
if (iDecimalPadding) {
|
|
1752
|
+
oOptions.minusSign = oOptions.minusSign.replace(rLeftToRightMark, "");
|
|
1753
|
+
}
|
|
1489
1754
|
// combine
|
|
1490
1755
|
if (bNegative) {
|
|
1491
1756
|
sResult = oOptions.minusSign;
|
|
@@ -1494,81 +1759,29 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1494
1759
|
if (sFractionPart) {
|
|
1495
1760
|
sResult += oOptions.decimalSeparator + sFractionPart;
|
|
1496
1761
|
}
|
|
1497
|
-
|
|
1762
|
+
const bUseCompactPattern = oShortFormat && oShortFormat.formatString && oOptions.showScale;
|
|
1763
|
+
let sCompactPattern;
|
|
1764
|
+
if (bUseCompactPattern) {
|
|
1498
1765
|
// Get correct format string based on actual decimal/fraction digits
|
|
1499
|
-
// the plural category of a compact number is determined for the reduced short number without
|
|
1500
|
-
// notation, e.g. "1.2M" must check "1.2"
|
|
1766
|
+
// the plural category of a compact number/currency is determined for the reduced short number without
|
|
1767
|
+
// compact notation, e.g. "1.2M" must check "1.2"
|
|
1768
|
+
// (see CLDR "decimalFormat-short" and "decimalFormat-long" or "currencyFormat-short")
|
|
1501
1769
|
sPluralCategory = this._getPluralCategory(sIntegerPart, sFractionPart);
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
sResult = sResult.replace(/'.'/g, ".");
|
|
1770
|
+
sCompactPattern = this.getCompactPattern(oOptions.type, oOptions.style, oShortFormat.key, sPluralCategory, oOptions.trailingCurrencyCode, bIndianCurrency, sMeasure && oOptions.showMeasure, sCurrencySymbolOrCode, bNegative);
|
|
1771
|
+
if (oOptions.type !== mNumberType.CURRENCY) {
|
|
1772
|
+
// inject formatted shortValue in the formatString
|
|
1773
|
+
sResult = sCompactPattern.replace(oShortFormat.valueSubString, sResult);
|
|
1774
|
+
}
|
|
1508
1775
|
}
|
|
1509
1776
|
if (oOptions.type === mNumberType.CURRENCY) {
|
|
1510
|
-
sPattern = oOptions.
|
|
1511
|
-
|
|
1512
|
-
var sStyle;
|
|
1513
|
-
|
|
1514
|
-
// Currency formatting has only short style (no long)
|
|
1515
|
-
if (oOptions.trailingCurrencyCode) {
|
|
1516
|
-
sStyle = "sap-short";
|
|
1517
|
-
} else {
|
|
1518
|
-
sStyle = "short";
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
// Get correct format string based on actual decimal/fraction digits
|
|
1522
|
-
// the plural category of a compact currency is determined for the reduced short number without compact
|
|
1523
|
-
// notation, e.g. "1.2M" must check "1.2" (see CLDR "currencyFormat-short")
|
|
1524
|
-
sPluralCategory = this._getPluralCategory(sIntegerPart, sFractionPart);
|
|
1525
|
-
if (bIndianCurrency) {
|
|
1526
|
-
sPattern = getIndianCurrencyFormat(sStyle, oShortFormat.key, sPluralCategory);
|
|
1527
|
-
} else {
|
|
1528
|
-
sPattern = this.oLocaleData.getCurrencyFormat(sStyle, oShortFormat.key, sPluralCategory);
|
|
1529
|
-
}
|
|
1530
|
-
//formatString may contain '.' (quoted to differentiate them decimal separator)
|
|
1531
|
-
//which must be replaced with .
|
|
1532
|
-
sPattern = sPattern.replace(/'.'/g, ".");
|
|
1533
|
-
}
|
|
1534
|
-
|
|
1535
|
-
// The currency pattern is defined in some locale, for example in "ko", as: ¤#,##0.00;(¤#,##0.00)
|
|
1536
|
-
// where the pattern after ';' should be used for negative numbers.
|
|
1537
|
-
// Therefore it's needed to check whether the pattern contains ';' and use the later part for
|
|
1538
|
-
// negative values
|
|
1539
|
-
aPatternParts = sPattern.split(";");
|
|
1540
|
-
if (aPatternParts.length === 2) {
|
|
1541
|
-
sPattern = bNegative ? aPatternParts[1] : aPatternParts[0];
|
|
1542
|
-
if (bNegative) {
|
|
1543
|
-
sResult = sResult.substring(oOptions.minusSign.length);
|
|
1544
|
-
}
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
// check if we need to render a symbol instead of a currency-code
|
|
1548
|
-
if (!oOptions.currencyCode) {
|
|
1549
|
-
var sSymbol;
|
|
1550
|
-
// custom currencies provided
|
|
1551
|
-
if (oOptions.customCurrencies && typeof oOptions.customCurrencies === "object") {
|
|
1552
|
-
// the custom currency symbol map was preprocessed on instance creation
|
|
1553
|
-
sSymbol = this.mKnownCurrencySymbols[sMeasure];
|
|
1554
|
-
} else {
|
|
1555
|
-
sSymbol = this.oLocaleData.getCurrencySymbol(sMeasure);
|
|
1556
|
-
}
|
|
1557
|
-
if (sSymbol && sSymbol !== sMeasure) {
|
|
1558
|
-
sMeasure = sSymbol;
|
|
1559
|
-
}
|
|
1560
|
-
}
|
|
1561
|
-
sResult = this._composeCurrencyResult(sPattern, sResult, sMeasure, {
|
|
1562
|
-
showMeasure: oOptions.showMeasure,
|
|
1563
|
-
negative: bNegative,
|
|
1564
|
-
minusSign: oOptions.minusSign
|
|
1565
|
-
});
|
|
1777
|
+
sPattern = bUseCompactPattern ? sCompactPattern : this.getCurrencyPattern(oOptions.currencyContext, oOptions.trailingCurrencyCode, sMeasure && oOptions.showMeasure, sCurrencySymbolOrCode, bNegative);
|
|
1778
|
+
sResult = NumberFormat._composeCurrencyResult(sPattern, sResult, sCurrencySymbolOrCode, oOptions.minusSign, bNegative);
|
|
1566
1779
|
}
|
|
1567
1780
|
|
|
1568
1781
|
// format percent values:
|
|
1569
1782
|
if (oOptions.type === mNumberType.PERCENT) {
|
|
1570
1783
|
sPattern = oOptions.pattern;
|
|
1571
|
-
sResult = sPattern.replace(
|
|
1784
|
+
sResult = sPattern.replace(rNumberPattern, sResult);
|
|
1572
1785
|
sResult = sResult.replace(/%/, oOptions.percentSign);
|
|
1573
1786
|
}
|
|
1574
1787
|
if (oOptions.showMeasure && sMeasure && oOptions.type === mNumberType.UNIT) {
|
|
@@ -1589,9 +1802,46 @@ NumberFormat.prototype.format = function (vValue, sMeasure) {
|
|
|
1589
1802
|
}
|
|
1590
1803
|
sResult = sPattern.replace("{0}", sResult);
|
|
1591
1804
|
}
|
|
1805
|
+
let iDecimalPaddingLength = iDecimalPadding - sFractionPart.length;
|
|
1806
|
+
if (iDecimalPaddingLength > 0) {
|
|
1807
|
+
const bNegativeAccounting = sResult[sResult.length - 1] === ")";
|
|
1808
|
+
const sCharPunctuationSpace = "\u2008";
|
|
1809
|
+
if (sFractionPart) {
|
|
1810
|
+
if (bNegativeAccounting) {
|
|
1811
|
+
// the ")" and the CHAR_PUNCTUATION_SPACE u2008 have a combined width close to the width of a
|
|
1812
|
+
// CHAR_FIGURE_SPACE u2007
|
|
1813
|
+
sResult += sCharPunctuationSpace;
|
|
1814
|
+
iDecimalPaddingLength = iDecimalPaddingLength - 1;
|
|
1815
|
+
}
|
|
1816
|
+
} else if (!bNegativeAccounting) {
|
|
1817
|
+
// only add CHAR_PUNCTUATION_SPACE u2008 if there is no ")" at the end
|
|
1818
|
+
sResult += sCharPunctuationSpace;
|
|
1819
|
+
}
|
|
1820
|
+
sResult += "\u2007".repeat(iDecimalPaddingLength); // CHAR_FIGURE_SPACE u2007
|
|
1821
|
+
}
|
|
1592
1822
|
return this._addOriginInfo(sResult);
|
|
1593
1823
|
};
|
|
1594
1824
|
|
|
1825
|
+
/**
|
|
1826
|
+
* Gets the currency symbol or the currency code for the given currency code depending on the given format options.
|
|
1827
|
+
*
|
|
1828
|
+
* @param {string} sCurrencyCode
|
|
1829
|
+
* The currency code
|
|
1830
|
+
* @param {boolean} bCurrencyCode
|
|
1831
|
+
* Whether to show the currency code instead of the currency symbol, see {@link Numberformat.getCurrencyInstance}
|
|
1832
|
+
* @returns {string}
|
|
1833
|
+
* The currency symbol or the currency code
|
|
1834
|
+
*
|
|
1835
|
+
* @private
|
|
1836
|
+
*/
|
|
1837
|
+
NumberFormat.prototype.getCurrencySymbolOrCode = function (sCurrencyCode, bCurrencyCode) {
|
|
1838
|
+
if (bCurrencyCode) {
|
|
1839
|
+
return sCurrencyCode;
|
|
1840
|
+
}
|
|
1841
|
+
// the custom currency symbol map was preprocessed on instance creation
|
|
1842
|
+
return (typeof this.oFormatOptions.customCurrencies === "object" ? this.mKnownCurrencySymbols[sCurrencyCode] : this.oLocaleData.getCurrencySymbol(sCurrencyCode)) || sCurrencyCode;
|
|
1843
|
+
};
|
|
1844
|
+
|
|
1595
1845
|
/**
|
|
1596
1846
|
* Gets the plural category for the given number information. With a given <code>oShortFormat</code>
|
|
1597
1847
|
* the category is determined based on the compact notation.
|
|
@@ -1629,54 +1879,46 @@ NumberFormat.prototype._addOriginInfo = function (sResult) {
|
|
|
1629
1879
|
}
|
|
1630
1880
|
return sResult;
|
|
1631
1881
|
};
|
|
1632
|
-
NumberFormat.prototype._composeCurrencyResult = function (sPattern, sFormattedNumber, sMeasure, oOptions) {
|
|
1633
|
-
var sMinusSign = oOptions.minusSign;
|
|
1634
|
-
sPattern = sPattern.replace(/[0#.,]+/, sFormattedNumber);
|
|
1635
|
-
if (oOptions.showMeasure && sMeasure) {
|
|
1636
|
-
var sPlaceHolder = "\u00a4",
|
|
1637
|
-
mRegex = {
|
|
1638
|
-
"[:digit:]": rDigit,
|
|
1639
|
-
"[[:^S:]&[:^Z:]]": rNotSAndNotZ
|
|
1640
|
-
},
|
|
1641
|
-
iMeasureStart = sPattern.indexOf(sPlaceHolder),
|
|
1642
|
-
// determine whether the number is before the measure or after it by comparing the position of measure placeholder with half of the length of the pattern string
|
|
1643
|
-
sPosition = iMeasureStart < sPattern.length / 2 ? "after" : "before",
|
|
1644
|
-
oSpacingSetting = this.oLocaleData.getCurrencySpacing(sPosition),
|
|
1645
|
-
sCurrencyChar = sPosition === "after" ? sMeasure.charAt(sMeasure.length - 1) : sMeasure.charAt(0),
|
|
1646
|
-
sNumberChar,
|
|
1647
|
-
rCurrencyChar = mRegex[oSpacingSetting.currencyMatch],
|
|
1648
|
-
rNumberChar = mRegex[oSpacingSetting.surroundingMatch],
|
|
1649
|
-
iInsertPos;
|
|
1650
|
-
sPattern = sPattern.replace(sPlaceHolder, sMeasure);
|
|
1651
|
-
sNumberChar = sPosition === "after" ? sPattern.charAt(iMeasureStart + sMeasure.length) : sPattern.charAt(iMeasureStart - 1);
|
|
1652
|
-
if (rCurrencyChar && rCurrencyChar.test(sCurrencyChar) && rNumberChar && rNumberChar.test(sNumberChar)) {
|
|
1653
|
-
// when both checks are valid, insert the defined space
|
|
1654
|
-
|
|
1655
|
-
if (sPosition === "after") {
|
|
1656
|
-
iInsertPos = iMeasureStart + sMeasure.length;
|
|
1657
|
-
} else {
|
|
1658
|
-
iInsertPos = iMeasureStart;
|
|
1659
|
-
}
|
|
1660
1882
|
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1883
|
+
/**
|
|
1884
|
+
* Replaces the amount, measure, and minus sign parts in the given pattern with the given values and returns the
|
|
1885
|
+
* result.
|
|
1886
|
+
*
|
|
1887
|
+
* @param {string} sPattern
|
|
1888
|
+
* The currency pattern, e.g. "¤#,##0.00;(¤#,##0.00)", "¤#,##0.00;¤-#,##0.00", "#,##0.00", or "¤ 000K"
|
|
1889
|
+
* @param {string} sAmount
|
|
1890
|
+
* The formatted amount, e.g. "1,234.56"
|
|
1891
|
+
* @param {string} sMeasure
|
|
1892
|
+
* The currency symbol or code
|
|
1893
|
+
* @param {string} sMinusSign
|
|
1894
|
+
* The locale specific minus sign
|
|
1895
|
+
* @param {boolean} bNegative
|
|
1896
|
+
* Whether the amount is negative
|
|
1897
|
+
* @returns {string}
|
|
1898
|
+
* The resulting string after replacing the amount, measure, and minus sign parts in the given pattern with the
|
|
1899
|
+
* given values
|
|
1900
|
+
*
|
|
1901
|
+
* @private
|
|
1902
|
+
*/
|
|
1903
|
+
NumberFormat._composeCurrencyResult = function (sPattern, sAmount, sMeasure, sMinusSign, bNegative) {
|
|
1904
|
+
const aPatternParts = sPattern.split(";");
|
|
1905
|
+
if (aPatternParts.length === 2) {
|
|
1906
|
+
sPattern = aPatternParts[bNegative ? 1 : 0];
|
|
1907
|
+
if (bNegative) {
|
|
1908
|
+
sAmount = sAmount.slice(sMinusSign.length);
|
|
1671
1909
|
}
|
|
1672
|
-
} else {
|
|
1673
|
-
// If measure is not shown, also remove whitespace next to the measure symbol
|
|
1674
|
-
sPattern = sPattern.replace(/\s*\u00a4\s*/, "");
|
|
1675
1910
|
}
|
|
1676
|
-
|
|
1677
|
-
|
|
1911
|
+
let sResult = sPattern.replace("-", sMinusSign).replace(rNumberPattern, sAmount).replace("\u00a4", sMeasure);
|
|
1912
|
+
if (bNegative) {
|
|
1913
|
+
// when no space is inserted between measure and number
|
|
1914
|
+
// and when the number is negative and the measure is shown before the number
|
|
1915
|
+
// a zero-width non-breakable space ("\ufeff") is inserted before the minus sign
|
|
1916
|
+
// in order to prevent the formatted currency number from being wrapped after the
|
|
1917
|
+
// minus sign when the space isn't enough for displaying the currency number within
|
|
1918
|
+
// one line
|
|
1919
|
+
sResult = sResult.replace(sMeasure + sMinusSign, sMeasure + "\ufeff" + sMinusSign);
|
|
1678
1920
|
}
|
|
1679
|
-
return
|
|
1921
|
+
return sResult;
|
|
1680
1922
|
};
|
|
1681
1923
|
|
|
1682
1924
|
/**
|
|
@@ -1701,7 +1943,7 @@ NumberFormat.prototype.parse = function (sValue) {
|
|
|
1701
1943
|
sPlusMinusSigns = quote(sPlusSigns + sMinusSigns),
|
|
1702
1944
|
sGroupingSeparator = quote(oOptions.groupingSeparator),
|
|
1703
1945
|
sDecimalSeparator = quote(oOptions.decimalSeparator),
|
|
1704
|
-
sRegExpFloat = "^\\s*([" + sPlusMinusSigns + "]?(?:[0-9" + sGroupingSeparator + "]+|[0-9" + sGroupingSeparator + "]*" + sDecimalSeparator + "[0-9]*)(?:[eE][+-][0-9]+)?)\\s*$",
|
|
1946
|
+
sRegExpFloat = "^\\s*([" + sPlusMinusSigns + "]?(?:[0-9" + sGroupingSeparator + "]+|[0-9" + sGroupingSeparator + "]*" + sDecimalSeparator + "[0-9]*)(?:[eE][+-]?[0-9]+)?)\\s*$",
|
|
1705
1947
|
sRegExpInt = "^\\s*([" + sPlusMinusSigns + "]?[0-9" + sGroupingSeparator + "]+)\\s*$",
|
|
1706
1948
|
oGroupingRegExp = new RegExp(sGroupingSeparator, "g"),
|
|
1707
1949
|
oDecimalRegExp = new RegExp(sDecimalSeparator, "g"),
|
|
@@ -1714,8 +1956,13 @@ NumberFormat.prototype.parse = function (sValue) {
|
|
|
1714
1956
|
vResult = 0,
|
|
1715
1957
|
oShort,
|
|
1716
1958
|
vEmptyParseValue;
|
|
1959
|
+
if (typeof sValue !== "string" && !(sValue instanceof String)) {
|
|
1960
|
+
return null;
|
|
1961
|
+
}
|
|
1962
|
+
sValue = FormatUtils.normalize(sValue).trim();
|
|
1717
1963
|
if (sValue === "") {
|
|
1718
|
-
|
|
1964
|
+
const bUnitOrCurrency = oOptions.type === mNumberType.CURRENCY || oOptions.type === mNumberType.UNIT;
|
|
1965
|
+
if (!oOptions.showNumber && !bUnitOrCurrency) {
|
|
1719
1966
|
return null;
|
|
1720
1967
|
}
|
|
1721
1968
|
vEmptyParseValue = oOptions.emptyString;
|
|
@@ -1724,15 +1971,15 @@ NumberFormat.prototype.parse = function (sValue) {
|
|
|
1724
1971
|
if (oOptions.parseAsString && (oOptions.emptyString === 0 || isNaN(oOptions.emptyString))) {
|
|
1725
1972
|
vEmptyParseValue = oOptions.emptyString + "";
|
|
1726
1973
|
}
|
|
1727
|
-
if (
|
|
1974
|
+
if (bUnitOrCurrency) {
|
|
1975
|
+
if (!oOptions.showNumber) {
|
|
1976
|
+
return [undefined, vEmptyParseValue];
|
|
1977
|
+
}
|
|
1728
1978
|
return [vEmptyParseValue, undefined];
|
|
1729
1979
|
} else {
|
|
1730
1980
|
return vEmptyParseValue;
|
|
1731
1981
|
}
|
|
1732
1982
|
}
|
|
1733
|
-
if (typeof sValue !== "string" && !(sValue instanceof String)) {
|
|
1734
|
-
return null;
|
|
1735
|
-
}
|
|
1736
1983
|
if (oOptions.groupingSeparator === oOptions.decimalSeparator) {
|
|
1737
1984
|
Log.error("The grouping and decimal separator both have the same value '" + oOptions.groupingSeparator + "'. " + "They must be different from each other such that values can be parsed correctly.");
|
|
1738
1985
|
}
|
|
@@ -1839,13 +2086,10 @@ NumberFormat.prototype.parse = function (sValue) {
|
|
|
1839
2086
|
}
|
|
1840
2087
|
}
|
|
1841
2088
|
|
|
1842
|
-
// remove the RTL special characters before the string is matched with the regex
|
|
1843
|
-
sValue = sValue.replace(/[\u202a\u200e\u202c\u202b\u200f]/g, "");
|
|
1844
|
-
|
|
1845
2089
|
// remove all white spaces because when grouping separator is a non-breaking space (russian and french for example)
|
|
1846
2090
|
// user will not input it this way. Also white spaces or grouping separator can be ignored by determining the value
|
|
1847
2091
|
sValue = sValue.replace(rAllWhiteSpaces, "");
|
|
1848
|
-
oShort = getNumberFromShortened(sValue,
|
|
2092
|
+
oShort = this.getNumberFromShortened(sValue, bIndianCurrency);
|
|
1849
2093
|
if (oShort) {
|
|
1850
2094
|
sValue = oShort.number;
|
|
1851
2095
|
}
|
|
@@ -1961,7 +2205,7 @@ NumberFormat.prototype.getScale = function () {
|
|
|
1961
2205
|
if (this.oFormatOptions.style !== "short" && this.oFormatOptions.style !== "long" || this.oFormatOptions.shortRefNumber === undefined) {
|
|
1962
2206
|
return;
|
|
1963
2207
|
}
|
|
1964
|
-
var oShortFormat = getShortenedFormat(this.oFormatOptions.shortRefNumber, this.oFormatOptions
|
|
2208
|
+
var oShortFormat = this.getShortenedFormat(this.oFormatOptions.shortRefNumber, this.oFormatOptions),
|
|
1965
2209
|
sScale;
|
|
1966
2210
|
if (oShortFormat && oShortFormat.formatString) {
|
|
1967
2211
|
// remove the placeholder of number
|
|
@@ -1974,10 +2218,23 @@ NumberFormat.prototype.getScale = function () {
|
|
|
1974
2218
|
}
|
|
1975
2219
|
}
|
|
1976
2220
|
};
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
2221
|
+
|
|
2222
|
+
/**
|
|
2223
|
+
* Moves the decimal seperator of the given number by the given steps to the right or left.
|
|
2224
|
+
*
|
|
2225
|
+
* @param {number|string} vValue
|
|
2226
|
+
* The number
|
|
2227
|
+
* @param {int} iStep
|
|
2228
|
+
* The number of decimal places to shift the "."; positive values shift to the right, negative values shift to the
|
|
2229
|
+
* left
|
|
2230
|
+
* @param {boolean} bNormalize
|
|
2231
|
+
* Whether the result is normalized if <code>vValue</code> is of type "string"; that means whether trailing zeros
|
|
2232
|
+
* are removed and whether scientific notation is resolved to a decimal string without exponent
|
|
2233
|
+
* @returns {number|string|null}
|
|
2234
|
+
* The number with shifted decimal point; or <code>null</code> if the given value is neither of type "number", nor
|
|
2235
|
+
* of type "string"
|
|
2236
|
+
*/
|
|
2237
|
+
NumberFormat._shiftDecimalPoint = function (vValue, iStep, bNormalize) {
|
|
1981
2238
|
var sMinus = "";
|
|
1982
2239
|
var aExpParts = vValue.toString().toLowerCase().split("e");
|
|
1983
2240
|
if (typeof vValue === "number") {
|
|
@@ -1988,7 +2245,7 @@ NumberFormat._shiftDecimalPoint = function (vValue, iStep) {
|
|
|
1988
2245
|
iStep = aExpParts[1] ? +aExpParts[1] + iStep : iStep;
|
|
1989
2246
|
return +(aExpParts[0] + "e" + iStep);
|
|
1990
2247
|
} else if (typeof vValue === "string") {
|
|
1991
|
-
if (parseFloat(vValue) === 0 && iStep >= 0) {
|
|
2248
|
+
if (!bNormalize && parseFloat(vValue) === 0 && iStep >= 0) {
|
|
1992
2249
|
// input "00000" should become "0"
|
|
1993
2250
|
// input "000.000" should become "0.000" to keep precision of decimals
|
|
1994
2251
|
// input "1e-1337" should remain "1e-1337" in order to keep the precision
|
|
@@ -1999,7 +2256,7 @@ NumberFormat._shiftDecimalPoint = function (vValue, iStep) {
|
|
|
1999
2256
|
// The minus sign will be added to the final result again.
|
|
2000
2257
|
var sFirstChar = aExpParts[0].charAt(0);
|
|
2001
2258
|
sMinus = sFirstChar === "-" ? sFirstChar : "";
|
|
2002
|
-
if (sMinus) {
|
|
2259
|
+
if (sMinus || sFirstChar === "+") {
|
|
2003
2260
|
aExpParts[0] = aExpParts[0].slice(1);
|
|
2004
2261
|
}
|
|
2005
2262
|
vValue = aExpParts[0];
|
|
@@ -2031,20 +2288,174 @@ NumberFormat._shiftDecimalPoint = function (vValue, iStep) {
|
|
|
2031
2288
|
vValue = vValue.replace(".", "");
|
|
2032
2289
|
sInt = vValue.substring(0, iAfterMovePos);
|
|
2033
2290
|
sDecimal = vValue.substring(iAfterMovePos);
|
|
2034
|
-
|
|
2035
2291
|
// remove unnecessary leading zeros
|
|
2036
2292
|
sInt = sInt.replace(rLeadingZeros, "$1$2");
|
|
2293
|
+
if (bNormalize) {
|
|
2294
|
+
sDecimal = sDecimal.replace(rTrailingZeros, "");
|
|
2295
|
+
}
|
|
2037
2296
|
return sMinus + sInt + (sDecimal ? "." + sDecimal : "");
|
|
2038
2297
|
} else {
|
|
2039
2298
|
// can't shift decimal point in this case
|
|
2040
2299
|
return null;
|
|
2041
2300
|
}
|
|
2042
2301
|
};
|
|
2043
|
-
|
|
2302
|
+
|
|
2303
|
+
/**
|
|
2304
|
+
* Checks whether there is a letter next to the number using the given currency pattern.
|
|
2305
|
+
*
|
|
2306
|
+
* @param {string} sPattern
|
|
2307
|
+
* The currency pattern, e.g. "¤#,##0.00;(¤#,##0.00)" or "¤ 000K"
|
|
2308
|
+
* @param {string} sCurrency
|
|
2309
|
+
* The currency code or the currency symbol to check, e.g. "USD" or "$"
|
|
2310
|
+
* @param {boolean} bNegative
|
|
2311
|
+
* Whether the value to be formatted is negative
|
|
2312
|
+
* @returns {boolean}
|
|
2313
|
+
* Whether there is a letter next to the number for the given pattern and currency
|
|
2314
|
+
*
|
|
2315
|
+
* @private
|
|
2316
|
+
*/
|
|
2317
|
+
NumberFormat.isAlphaNextToNumber = function (sPattern, sCurrency, bNegative) {
|
|
2318
|
+
if (!sPattern || !sCurrency) {
|
|
2319
|
+
return false;
|
|
2320
|
+
}
|
|
2321
|
+
const aPatterns = sPattern.split(";");
|
|
2322
|
+
sPattern = (aPatterns[bNegative ? 1 : 0] || aPatterns[0]).replace(rAllRTLCharacters, "");
|
|
2323
|
+
const aMatches = rSplitCurrencyPattern.exec(sPattern);
|
|
2324
|
+
|
|
2325
|
+
// number in front of the currency placeholder
|
|
2326
|
+
if (aMatches[1]) {
|
|
2327
|
+
return rStartsWithLetter.test(sCurrency) && !aMatches[2];
|
|
2328
|
+
}
|
|
2329
|
+
|
|
2330
|
+
// currency placeholder in front of the number
|
|
2331
|
+
return !aMatches[4] // no characters between the placeholder and the number
|
|
2332
|
+
&& rEndsWithLetter.test(sCurrency) // currency ends with a letter
|
|
2333
|
+
// if there is no separate negative pattern and the value is negative, there is a minus sign between
|
|
2334
|
+
// the currency and the number, so there is no need for the alphaNextToNumber pattern
|
|
2335
|
+
&& (!bNegative || aPatterns.length !== 1);
|
|
2336
|
+
};
|
|
2337
|
+
|
|
2338
|
+
/**
|
|
2339
|
+
* Gets the compact decimal or currency pattern for the given power of ten and plural category.
|
|
2340
|
+
*
|
|
2341
|
+
* @param {"integer"|"float"|"currency"|"unit"|"percent"} sType
|
|
2342
|
+
* The number format type
|
|
2343
|
+
* @param {"long"|"short"} sStyle
|
|
2344
|
+
* The style of the compact format
|
|
2345
|
+
* @param {string} sPowerOfTen
|
|
2346
|
+
* The power of ten
|
|
2347
|
+
* @param {"few"|"many"|"one"|"other"|"two"|"zero"} sPluralCategory
|
|
2348
|
+
* The plural category
|
|
2349
|
+
* @param {boolean} [bTrailingCurrencyCode]
|
|
2350
|
+
* Whether the currency code is formatted after the amount; only relevant if type "currency" is used
|
|
2351
|
+
* @param {boolean} [bIndianCurrency]
|
|
2352
|
+
* Whether to use the Indian currency format; only relevant if type "currency" is used
|
|
2353
|
+
* @param {boolean} [bShowMeasure]
|
|
2354
|
+
* Whether to show the measure
|
|
2355
|
+
* @param {string} [sCurrency]
|
|
2356
|
+
* The currency code or symbol
|
|
2357
|
+
* @param {boolean} [bNegative]
|
|
2358
|
+
* Whether the number is negative
|
|
2359
|
+
* @returns {string|undefined}
|
|
2360
|
+
* The compact decimal or currency pattern for the given power of ten and plural category; or
|
|
2361
|
+
* <code>undefined</code> if there is no pattern for the given parameters
|
|
2362
|
+
*
|
|
2363
|
+
* @private
|
|
2364
|
+
*/
|
|
2365
|
+
NumberFormat.prototype.getCompactPattern = function (sType, sStyle, sPowerOfTen, sPluralCategory, bTrailingCurrencyCode, bIndianCurrency, bShowMeasure, sCurrency, bNegative) {
|
|
2366
|
+
let sPattern;
|
|
2367
|
+
if (sType === mNumberType.CURRENCY) {
|
|
2368
|
+
if (bTrailingCurrencyCode) {
|
|
2369
|
+
sStyle = "sap-short";
|
|
2370
|
+
}
|
|
2371
|
+
if (bIndianCurrency) {
|
|
2372
|
+
sStyle += "-indian";
|
|
2373
|
+
}
|
|
2374
|
+
if (bShowMeasure) {
|
|
2375
|
+
// Use currency specific format because for some languages there is a difference between the
|
|
2376
|
+
// decimalFormat and the currencyFormat
|
|
2377
|
+
sPattern = this.oLocaleData.getCompactCurrencyPattern(sStyle, sPowerOfTen, sPluralCategory);
|
|
2378
|
+
if (NumberFormat.isAlphaNextToNumber(sPattern, sCurrency, bNegative)) {
|
|
2379
|
+
sPattern = this.oLocaleData.getCompactCurrencyPattern(sStyle, sPowerOfTen, sPluralCategory, "alphaNextToNumber") || sPattern;
|
|
2380
|
+
}
|
|
2381
|
+
} else {
|
|
2382
|
+
sPattern = this.oLocaleData.getCompactCurrencyPattern(sStyle, sPowerOfTen, sPluralCategory, "noCurrency");
|
|
2383
|
+
if (!sPattern) {
|
|
2384
|
+
if (sStyle.startsWith("sap-")) {
|
|
2385
|
+
sStyle = sStyle.slice(4);
|
|
2386
|
+
}
|
|
2387
|
+
sPattern = this.oLocaleData.getCompactDecimalPattern(sStyle, sPowerOfTen, sPluralCategory);
|
|
2388
|
+
}
|
|
2389
|
+
}
|
|
2390
|
+
} else {
|
|
2391
|
+
sPattern = this.oLocaleData.getCompactDecimalPattern(sStyle, sPowerOfTen, sPluralCategory);
|
|
2392
|
+
}
|
|
2393
|
+
|
|
2394
|
+
// pattern may contain a single quoted dot ('.') to differentiate them from decimal separator; replace it
|
|
2395
|
+
// with an unquoted dot (.)
|
|
2396
|
+
sPattern = sPattern?.replace(/'.'/g, ".");
|
|
2397
|
+
return sPattern;
|
|
2398
|
+
};
|
|
2399
|
+
|
|
2400
|
+
/**
|
|
2401
|
+
* Gets the locale specific currency pattern for the given parameters.
|
|
2402
|
+
*
|
|
2403
|
+
* @param {"accounting"|"standard"} sContext The context of the currency pattern
|
|
2404
|
+
* @param {boolean} [bShowTrailingCurrencyCode] Whether the currency code shall be shown after the amount
|
|
2405
|
+
* @param {boolean} [bShowMeasure] Whether to include the measure (currency code or currency symbol) in the pattern
|
|
2406
|
+
* @param {string} [sCurrency] The currency code or symbol to use
|
|
2407
|
+
* @param {boolean} [bNegative] Whether the current value is negative
|
|
2408
|
+
* @returns {string} The currency pattern
|
|
2409
|
+
*
|
|
2410
|
+
* @private
|
|
2411
|
+
*/
|
|
2412
|
+
NumberFormat.prototype.getCurrencyPattern = function (sContext, bShowTrailingCurrencyCode, bShowMeasure, sCurrency, bNegative) {
|
|
2413
|
+
if (bShowTrailingCurrencyCode) {
|
|
2414
|
+
sContext = "sap-" + sContext;
|
|
2415
|
+
}
|
|
2416
|
+
let sPattern = this.oLocaleData.getCurrencyPattern(sContext, bShowMeasure ? undefined : "noCurrency");
|
|
2417
|
+
if (bShowMeasure && NumberFormat.isAlphaNextToNumber(sPattern, sCurrency, bNegative)) {
|
|
2418
|
+
sPattern = this.oLocaleData.getCurrencyPattern(sContext, "alphaNextToNumber") || sPattern;
|
|
2419
|
+
}
|
|
2420
|
+
return sPattern;
|
|
2421
|
+
};
|
|
2422
|
+
|
|
2423
|
+
/**
|
|
2424
|
+
* Gets the compact decimal or currency format for the given value and parameters.
|
|
2425
|
+
*
|
|
2426
|
+
* @param {number|string} vValue
|
|
2427
|
+
* The value for which the shortened format is determined
|
|
2428
|
+
* @param {object} oOptions
|
|
2429
|
+
* The options used for getting the compact pattern
|
|
2430
|
+
* @param {int} [oOptions.precision = 2]
|
|
2431
|
+
* The maximum number of digits in the formatted representation of the number
|
|
2432
|
+
* @param {"long"|"short"} oOptions.style
|
|
2433
|
+
* The style of the compact format
|
|
2434
|
+
* @param {boolean} [oOptions.trailingCurrencyCode]
|
|
2435
|
+
* Whether the currency code is formatted after the amount; only relevant if type "currency" is used
|
|
2436
|
+
* @param {"integer"|"float"|"currency"|"unit"|"percent"} oOptions.type
|
|
2437
|
+
* The number format type
|
|
2438
|
+
* @param {boolean} [bIndianCurrency]
|
|
2439
|
+
* Whether to use the Indian currency format; only relevant if type "currency" is used
|
|
2440
|
+
*
|
|
2441
|
+
* @returns {object|undefined}
|
|
2442
|
+
* The compact decimal or currency format for the given value; or <code>undefined</code> if neither the "short"
|
|
2443
|
+
* or the "long" style is used, or if there is no compact format for the given parameters; the returned object
|
|
2444
|
+
* contains the following properties:
|
|
2445
|
+
* <ul>
|
|
2446
|
+
* <li><code>decimals</code>: The number of decimals used in the compact format pattern</li>
|
|
2447
|
+
* <li><code>formatString</code>: The compact format pattern to use</li>
|
|
2448
|
+
* <li><code>key</code>: The power of ten matching the given value</li>
|
|
2449
|
+
* <li><code>magnitude</code>: The divisor to get the compact number to show from the given value</li>
|
|
2450
|
+
* <li><code>valueSubString</code>: The number part of the format pattern</li>
|
|
2451
|
+
* </ul>
|
|
2452
|
+
*
|
|
2453
|
+
* @private
|
|
2454
|
+
*/
|
|
2455
|
+
NumberFormat.prototype.getShortenedFormat = function (vValue, oOptions, bIndianCurrency) {
|
|
2044
2456
|
var oShortFormat,
|
|
2045
2457
|
iKey,
|
|
2046
2458
|
sKey,
|
|
2047
|
-
sCldrFormat,
|
|
2048
2459
|
sStyle = oOptions.style,
|
|
2049
2460
|
iPrecision = oOptions.precision !== undefined ? oOptions.precision : 2;
|
|
2050
2461
|
if (sStyle != "short" && sStyle != "long") {
|
|
@@ -2052,7 +2463,7 @@ function getShortenedFormat(fValue, oOptions, oLocaleData, bIndianCurrency) {
|
|
|
2052
2463
|
}
|
|
2053
2464
|
for (var i = 0; i < 15; i++) {
|
|
2054
2465
|
iKey = Math.pow(10, i);
|
|
2055
|
-
if (rounding(Math.abs(
|
|
2466
|
+
if (rounding(Math.abs(vValue) / iKey, iPrecision - 1) < 10) {
|
|
2056
2467
|
break;
|
|
2057
2468
|
}
|
|
2058
2469
|
}
|
|
@@ -2060,19 +2471,7 @@ function getShortenedFormat(fValue, oOptions, oLocaleData, bIndianCurrency) {
|
|
|
2060
2471
|
|
|
2061
2472
|
// Use "other" format to find the right magnitude, the actual format will be retrieved later
|
|
2062
2473
|
// after the value has been calculated
|
|
2063
|
-
|
|
2064
|
-
if (oOptions.trailingCurrencyCode) {
|
|
2065
|
-
sStyle = "sap-short";
|
|
2066
|
-
}
|
|
2067
|
-
if (bIndianCurrency) {
|
|
2068
|
-
sCldrFormat = getIndianCurrencyFormat(sStyle, sKey, "other", true);
|
|
2069
|
-
} else {
|
|
2070
|
-
// Use currency specific format because for some languages there is a difference between the decimalFormat and the currencyFormat
|
|
2071
|
-
sCldrFormat = oLocaleData.getCurrencyFormat(sStyle, sKey, "other");
|
|
2072
|
-
}
|
|
2073
|
-
} else {
|
|
2074
|
-
sCldrFormat = oLocaleData.getDecimalFormat(sStyle, sKey, "other");
|
|
2075
|
-
}
|
|
2474
|
+
const sCldrFormat = this.getCompactPattern(oOptions.type, oOptions.style, sKey, "other", oOptions.trailingCurrencyCode, bIndianCurrency, oOptions.showMeasure);
|
|
2076
2475
|
if (!sCldrFormat || sCldrFormat == "0") {
|
|
2077
2476
|
//no format or special "0" format => number doesn't need to be shortened
|
|
2078
2477
|
return undefined;
|
|
@@ -2103,218 +2502,123 @@ function getShortenedFormat(fValue, oOptions, oLocaleData, bIndianCurrency) {
|
|
|
2103
2502
|
}
|
|
2104
2503
|
}
|
|
2105
2504
|
return oShortFormat;
|
|
2106
|
-
}
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
// spanish numbers e.g. for MRD in format for "one" is "00 MRD" therefore factor needs to be adjusted
|
|
2147
|
-
// german numbers e.g. for Mrd. in format for "one" is "0 Mrd." therefore number does not need to be adjusted
|
|
2148
|
-
// "0" => magnitude = key
|
|
2149
|
-
// "00" => magnitude = key / 10
|
|
2150
|
-
// "000" => magnitude = key / 100
|
|
2151
|
-
iFactor *= Math.pow(10, 1 - sValueSubString.length);
|
|
2152
|
-
|
|
2153
|
-
// if best result has no number yet or the new number is smaller that the current one set the new number as best result
|
|
2154
|
-
if (bestResult.number === undefined || sNumber.length < bestResult.number.length) {
|
|
2155
|
-
bestResult.number = sNumber;
|
|
2156
|
-
bestResult.factor = iFactor;
|
|
2157
|
-
}
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
};
|
|
2162
|
-
// iterate over all formats. Max: 100 000 000 000 000
|
|
2163
|
-
// find best result as format can have multiple matches:
|
|
2164
|
-
// * value can be contained one in another (de-DE): "Million" and "Millionen"
|
|
2165
|
-
// * end with each other (es-ES): "mil millones" and "millones"
|
|
2166
|
-
["long", "short"].forEach(function (sStyle) {
|
|
2167
|
-
iKey = 10;
|
|
2168
|
-
while (iKey < 1e15) {
|
|
2169
|
-
for (var i = 0; i < aPluralCategories.length; i++) {
|
|
2170
|
-
var sPluralCategory = aPluralCategories[i];
|
|
2171
|
-
fnGetFactor(sPluralCategory, iKey, sStyle);
|
|
2172
|
-
}
|
|
2173
|
-
iKey = iKey * 10;
|
|
2174
|
-
}
|
|
2175
|
-
});
|
|
2176
|
-
|
|
2177
|
-
// For india currencies try lakhs/crores
|
|
2178
|
-
if (bIndianCurrency && !sNumber) {
|
|
2179
|
-
iKey = 10;
|
|
2180
|
-
while (iKey < 1e15) {
|
|
2181
|
-
for (var i = 0; i < aPluralCategories.length; i++) {
|
|
2182
|
-
var sPluralCategory = aPluralCategories[i];
|
|
2183
|
-
fnGetFactor(sPluralCategory, iKey, "short", true);
|
|
2505
|
+
};
|
|
2506
|
+
|
|
2507
|
+
/**
|
|
2508
|
+
* Returns an object with two properties. The first is the number substring of the given <code>sValue</code>.
|
|
2509
|
+
* The second property is the factor with which the determined number must be multiplied to resolve
|
|
2510
|
+
* the short format.
|
|
2511
|
+
* If the number of the given <code>sValue</code> is larger than 100 000 000 000 000 no short format will be found
|
|
2512
|
+
* and <code>undefined</code> is returned.
|
|
2513
|
+
*
|
|
2514
|
+
* @example
|
|
2515
|
+
* Formatted value to be parsed: "123K"
|
|
2516
|
+
* Chosen short format: "100000-other": "000K",
|
|
2517
|
+
* Number Substring: "123"
|
|
2518
|
+
* Factor: 1000
|
|
2519
|
+
* Parsed number: 123 * 1000 = 123000
|
|
2520
|
+
*
|
|
2521
|
+
* @param {string} sValue The value for which the short format shall be determined
|
|
2522
|
+
* @param {boolean} bIndianCurrency Whether the the value has to be treated as Indian currency
|
|
2523
|
+
*
|
|
2524
|
+
* @returns {{number: string, factor: number}|undefined}
|
|
2525
|
+
* An object containing the number substring of the given <code>sValue</code>, e.g. <code>"123"</code> and
|
|
2526
|
+
* the factor with which the determined number must be multiplied to resolve the short format;
|
|
2527
|
+
* <code>undefined</code> if no short format is found for the given <code>sValue</code>
|
|
2528
|
+
*
|
|
2529
|
+
* @private
|
|
2530
|
+
*/
|
|
2531
|
+
NumberFormat.prototype.getNumberFromShortened = function (sValue, bIndianCurrency) {
|
|
2532
|
+
const aPluralCategories = this.oLocaleData.getPluralCategories();
|
|
2533
|
+
const oBestResult = {
|
|
2534
|
+
number: undefined,
|
|
2535
|
+
factor: 1
|
|
2536
|
+
};
|
|
2537
|
+
const oIndianBestResult = {
|
|
2538
|
+
number: undefined,
|
|
2539
|
+
factor: 1
|
|
2540
|
+
};
|
|
2541
|
+
for (const iPowerOfTen of aPowerOfTens) {
|
|
2542
|
+
for (const sPluralCategory of aPluralCategories) {
|
|
2543
|
+
if (bIndianCurrency) {
|
|
2544
|
+
this.updateBestResult(oIndianBestResult, sPluralCategory, iPowerOfTen, "short-indian", sValue);
|
|
2184
2545
|
}
|
|
2185
|
-
|
|
2546
|
+
this.updateBestResult(oBestResult, sPluralCategory, iPowerOfTen, "long", sValue);
|
|
2547
|
+
this.updateBestResult(oBestResult, sPluralCategory, iPowerOfTen, "short", sValue);
|
|
2186
2548
|
}
|
|
2187
2549
|
}
|
|
2188
|
-
if (
|
|
2189
|
-
return;
|
|
2550
|
+
if (oIndianBestResult.number) {
|
|
2551
|
+
return oIndianBestResult;
|
|
2552
|
+
} else if (oBestResult.number) {
|
|
2553
|
+
return oBestResult;
|
|
2190
2554
|
}
|
|
2191
|
-
return
|
|
2192
|
-
}
|
|
2555
|
+
return undefined;
|
|
2556
|
+
};
|
|
2193
2557
|
|
|
2194
2558
|
/**
|
|
2195
|
-
*
|
|
2196
|
-
*
|
|
2197
|
-
*
|
|
2559
|
+
* Updates the number and factor in the given reference object based on the plural category,
|
|
2560
|
+
* power of ten, and style with the best match if one can be found for a given value.
|
|
2561
|
+
*
|
|
2562
|
+
* @param {{number: string, factor: number}} oBestResult
|
|
2563
|
+
* A reference in which the number and factor determined by this function will be stored
|
|
2564
|
+
* @param {"zero"|"one"|"two"|"few"|"many"} sPluralCategory
|
|
2565
|
+
* The plural category
|
|
2566
|
+
* @param {int} iPowerOfTen
|
|
2567
|
+
* The power of ten, max: 100 000 000 000 000
|
|
2568
|
+
* @param {"long"|"short"|"short-indian"} sStyle
|
|
2569
|
+
* The style
|
|
2570
|
+
* @param {string} sValue
|
|
2571
|
+
* The value for which the number and factor has to be determined
|
|
2572
|
+
*
|
|
2573
|
+
* @private
|
|
2198
2574
|
*/
|
|
2199
|
-
function
|
|
2200
|
-
|
|
2201
|
-
if (
|
|
2202
|
-
//
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
if (
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2575
|
+
NumberFormat.prototype.updateBestResult = function (oBestResult, sPluralCategory, iPowerOfTen, sStyle, sValue) {
|
|
2576
|
+
let sCldrFormat = this.oLocaleData.getCompactDecimalPattern(sStyle, iPowerOfTen.toString(), sPluralCategory);
|
|
2577
|
+
if (sCldrFormat) {
|
|
2578
|
+
// Note: CLDR uses a non-breaking space and right-to-left mark u+200f in the format string
|
|
2579
|
+
sCldrFormat = FormatUtils.normalize(sCldrFormat, true);
|
|
2580
|
+
//formatString may contain '.' (quoted to differentiate them from decimal separator)
|
|
2581
|
+
//which must be replaced with .
|
|
2582
|
+
sCldrFormat = sCldrFormat.replace(/'.'/g, ".");
|
|
2583
|
+
const aMatch = sCldrFormat.match(rNumPlaceHolder);
|
|
2584
|
+
if (aMatch) {
|
|
2585
|
+
// determine unit -> may be on the beginning e.g. for he
|
|
2586
|
+
const sValueSubString = aMatch[0];
|
|
2587
|
+
const sScalingFactor = sCldrFormat.replace(sValueSubString, "");
|
|
2588
|
+
if (sScalingFactor && sValue.includes(sScalingFactor)) {
|
|
2589
|
+
// parse the number part like every other number and then use the factor to get the real number
|
|
2590
|
+
const sNumber = sValue.replace(sScalingFactor, "");
|
|
2591
|
+
// spanish numbers e.g. for MRD in format for "one" is "00 MRD" therefore factor needs to be
|
|
2592
|
+
// adjusted
|
|
2593
|
+
// german numbers e.g. for Mrd. in format for "one" is "0 Mrd." therefore number does not need to
|
|
2594
|
+
// be adjusted
|
|
2595
|
+
// "0" => magnitude = key
|
|
2596
|
+
// "00" => magnitude = key / 10
|
|
2597
|
+
// "000" => magnitude = key / 100
|
|
2598
|
+
const iFactor = iPowerOfTen * Math.pow(10, 1 - sValueSubString.length);
|
|
2599
|
+
if (oBestResult.number === undefined || sNumber.length < oBestResult.number.length) {
|
|
2600
|
+
oBestResult.number = sNumber;
|
|
2601
|
+
oBestResult.factor = iFactor;
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2215
2604
|
}
|
|
2216
2605
|
}
|
|
2217
|
-
|
|
2218
|
-
}
|
|
2219
|
-
function getIndianCurrencyFormat(sStyle, sKey, sPlural, bDecimal) {
|
|
2220
|
-
var sFormat,
|
|
2221
|
-
oCurrencyFormats = {
|
|
2222
|
-
"short": {
|
|
2223
|
-
"1000-one": "\xa40000",
|
|
2224
|
-
"1000-other": "\xa40000",
|
|
2225
|
-
"10000-one": "\xa400000",
|
|
2226
|
-
"10000-other": "\xa400000",
|
|
2227
|
-
"100000-one": "\xa40 Lk",
|
|
2228
|
-
"100000-other": "\xa40 Lk",
|
|
2229
|
-
"1000000-one": "\xa400 Lk",
|
|
2230
|
-
"1000000-other": "\xa400 Lk",
|
|
2231
|
-
"10000000-one": "\xa40 Cr",
|
|
2232
|
-
"10000000-other": "\xa40 Cr",
|
|
2233
|
-
"100000000-one": "\xa400 Cr",
|
|
2234
|
-
"100000000-other": "\xa400 Cr",
|
|
2235
|
-
"1000000000-one": "\xa4000 Cr",
|
|
2236
|
-
"1000000000-other": "\xa4000 Cr",
|
|
2237
|
-
"10000000000-one": "\xa40000 Cr",
|
|
2238
|
-
"10000000000-other": "\xa40000 Cr",
|
|
2239
|
-
"100000000000-one": "\xa400000 Cr",
|
|
2240
|
-
"100000000000-other": "\xa400000 Cr",
|
|
2241
|
-
"1000000000000-one": "\xa40 Lk Cr",
|
|
2242
|
-
"1000000000000-other": "\xa40 Lk Cr",
|
|
2243
|
-
"10000000000000-one": "\xa400 Lk Cr",
|
|
2244
|
-
"10000000000000-other": "\xa400 Lk Cr",
|
|
2245
|
-
"100000000000000-one": "\xa40 Cr Cr",
|
|
2246
|
-
"100000000000000-other": "\xa40 Cr Cr"
|
|
2247
|
-
},
|
|
2248
|
-
"sap-short": {
|
|
2249
|
-
"1000-one": "0000\xa0\xa4",
|
|
2250
|
-
"1000-other": "0000\xa0\xa4",
|
|
2251
|
-
"10000-one": "00000\xa0\xa4",
|
|
2252
|
-
"10000-other": "00000\xa0\xa4",
|
|
2253
|
-
"100000-one": "0 Lk\xa0\xa4",
|
|
2254
|
-
"100000-other": "0 Lk\xa0\xa4",
|
|
2255
|
-
"1000000-one": "00 Lk\xa0\xa4",
|
|
2256
|
-
"1000000-other": "00 Lk\xa0\xa4",
|
|
2257
|
-
"10000000-one": "0 Cr\xa0\xa4",
|
|
2258
|
-
"10000000-other": "0 Cr\xa0\xa4",
|
|
2259
|
-
"100000000-one": "00 Cr\xa0\xa4",
|
|
2260
|
-
"100000000-other": "00 Cr\xa0\xa4",
|
|
2261
|
-
"1000000000-one": "000 Cr\xa0\xa4",
|
|
2262
|
-
"1000000000-other": "000 Cr\xa0\xa4",
|
|
2263
|
-
"10000000000-one": "0000 Cr\xa0\xa4",
|
|
2264
|
-
"10000000000-other": "0000 Cr\xa0\xa4",
|
|
2265
|
-
"100000000000-one": "00000 Cr\xa0\xa4",
|
|
2266
|
-
"100000000000-other": "00000 Cr\xa0\xa4",
|
|
2267
|
-
"1000000000000-one": "0 Lk Cr\xa0\xa4",
|
|
2268
|
-
"1000000000000-other": "0 Lk Cr\xa0\xa4",
|
|
2269
|
-
"10000000000000-one": "00 Lk Cr\xa0\xa4",
|
|
2270
|
-
"10000000000000-other": "00 Lk Cr\xa0\xa4",
|
|
2271
|
-
"100000000000000-one": "0 Cr Cr\xa0\xa4",
|
|
2272
|
-
"100000000000000-other": "0 Cr Cr\xa0\xa4"
|
|
2273
|
-
}
|
|
2274
|
-
},
|
|
2275
|
-
oDecimalFormats = {
|
|
2276
|
-
"short": {
|
|
2277
|
-
"1000-one": "0000",
|
|
2278
|
-
"1000-other": "0000",
|
|
2279
|
-
"10000-one": "00000",
|
|
2280
|
-
"10000-other": "00000",
|
|
2281
|
-
"100000-one": "0 Lk",
|
|
2282
|
-
"100000-other": "0 Lk",
|
|
2283
|
-
"1000000-one": "00 Lk",
|
|
2284
|
-
"1000000-other": "00 Lk",
|
|
2285
|
-
"10000000-one": "0 Cr",
|
|
2286
|
-
"10000000-other": "0 Cr",
|
|
2287
|
-
"100000000-one": "00 Cr",
|
|
2288
|
-
"100000000-other": "00 Cr",
|
|
2289
|
-
"1000000000-one": "000 Cr",
|
|
2290
|
-
"1000000000-other": "000 Cr",
|
|
2291
|
-
"10000000000-one": "0000 Cr",
|
|
2292
|
-
"10000000000-other": "0000 Cr",
|
|
2293
|
-
"100000000000-one": "00000 Cr",
|
|
2294
|
-
"100000000000-other": "00000 Cr",
|
|
2295
|
-
"1000000000000-one": "0 Lk Cr",
|
|
2296
|
-
"1000000000000-other": "0 Lk Cr",
|
|
2297
|
-
"10000000000000-one": "00 Lk Cr",
|
|
2298
|
-
"10000000000000-other": "00 Lk Cr",
|
|
2299
|
-
"100000000000000-one": "0 Cr Cr",
|
|
2300
|
-
"100000000000000-other": "0 Cr Cr"
|
|
2301
|
-
}
|
|
2302
|
-
};
|
|
2303
|
-
// decimal format for short and sap-short is the same
|
|
2304
|
-
oDecimalFormats["sap-short"] = oDecimalFormats["short"];
|
|
2606
|
+
};
|
|
2305
2607
|
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2608
|
+
/**
|
|
2609
|
+
* Whether to show the currency code at the end based on the original format options and the global configuration.
|
|
2610
|
+
*
|
|
2611
|
+
* @returns {boolean} Whether to show trailing currency code
|
|
2612
|
+
*/
|
|
2613
|
+
NumberFormat.prototype.showTrailingCurrencyCode = function () {
|
|
2614
|
+
const oFormatOptions = this.oOriginalFormatOptions;
|
|
2615
|
+
// use default currency mode if custom pattern is given or currency code shall not be shown
|
|
2616
|
+
if (oFormatOptions?.pattern || oFormatOptions?.currencyCode === false) {
|
|
2617
|
+
return false;
|
|
2618
|
+
}
|
|
2619
|
+
return oFormatOptions?.trailingCurrencyCode !== undefined ? oFormatOptions.trailingCurrencyCode // overwritten by instance configuration
|
|
2620
|
+
: Formatting.getTrailingCurrencyCode();
|
|
2621
|
+
};
|
|
2318
2622
|
|
|
2319
2623
|
/**
|
|
2320
2624
|
* Checks if grouping is performed correctly (decimal separator is not confused with grouping separator).
|
|
@@ -2446,6 +2750,18 @@ NumberFormat.prototype._checkGrouping = function (sValueWithGrouping, oOptions,
|
|
|
2446
2750
|
return true;
|
|
2447
2751
|
};
|
|
2448
2752
|
|
|
2753
|
+
/**
|
|
2754
|
+
* Checks whether grouping will be enabled for this instance.
|
|
2755
|
+
*
|
|
2756
|
+
* @private
|
|
2757
|
+
*/
|
|
2758
|
+
NumberFormat.prototype.checkGroupingFormatOptions = function () {
|
|
2759
|
+
if (this.oFormatOptions.groupingEnabled && this.oFormatOptions.groupingSize <= 0) {
|
|
2760
|
+
Log.warning("Grouping is disabled due to non-positive groupingSize set to '" + this.oFormatOptions.groupingSize + "'.");
|
|
2761
|
+
this.oFormatOptions.groupingEnabled = false;
|
|
2762
|
+
}
|
|
2763
|
+
};
|
|
2764
|
+
|
|
2449
2765
|
/**
|
|
2450
2766
|
* Whether or not the given value is in scientific notation
|
|
2451
2767
|
*
|
|
@@ -2487,50 +2803,63 @@ function getInteger(sValue) {
|
|
|
2487
2803
|
}
|
|
2488
2804
|
return iInt;
|
|
2489
2805
|
}
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2806
|
+
|
|
2807
|
+
/**
|
|
2808
|
+
* Rounds the given value by the given number of fraction digits based on the given rounding mode.
|
|
2809
|
+
*
|
|
2810
|
+
* @param {number|string} vValue
|
|
2811
|
+
* The number to be rounded, may be a string or a number; has to be of type number if a custom rounding function
|
|
2812
|
+
* is used
|
|
2813
|
+
* @param {int|string} iMaxFractionDigits
|
|
2814
|
+
* The maximum number of fraction digits
|
|
2815
|
+
* @param {sap.ui.core.format.NumberFormat.RoundingMode|function(number,int):number} vRoundingMode
|
|
2816
|
+
* The rounding mode or a custom function for rounding which is called with the number and the number of decimal
|
|
2817
|
+
* digits that should be reserved; <b>using a function is deprecated since 1.121.0</b>; string based numbers are
|
|
2818
|
+
* not rounded via this custom function.
|
|
2819
|
+
* @returns {number|string}
|
|
2820
|
+
* The rounded value; the returned type is the same as the type of the given <code>vValue</code>
|
|
2821
|
+
*/
|
|
2822
|
+
function rounding(vValue, iMaxFractionDigits, vRoundingMode) {
|
|
2823
|
+
vRoundingMode = vRoundingMode || NumberFormat.RoundingMode.HALF_AWAY_FROM_ZERO;
|
|
2495
2824
|
iMaxFractionDigits = parseInt(iMaxFractionDigits);
|
|
2496
2825
|
|
|
2497
2826
|
// only round if it is required (number of fraction digits is bigger than the maxFractionDigits option)
|
|
2498
|
-
var sValue = "" +
|
|
2827
|
+
var sValue = "" + vValue;
|
|
2499
2828
|
if (!isScientificNotation(sValue)) {
|
|
2500
2829
|
var iIndexOfPoint = sValue.indexOf(".");
|
|
2501
2830
|
if (iIndexOfPoint < 0) {
|
|
2502
|
-
return
|
|
2831
|
+
return vValue;
|
|
2503
2832
|
}
|
|
2504
2833
|
if (sValue.substring(iIndexOfPoint + 1).length <= iMaxFractionDigits) {
|
|
2505
|
-
|
|
2834
|
+
if (typeof vValue === "string") {
|
|
2835
|
+
vValue = NumberFormat._shiftDecimalPoint(vValue, 0, true);
|
|
2836
|
+
}
|
|
2837
|
+
return vValue;
|
|
2506
2838
|
}
|
|
2507
2839
|
}
|
|
2508
|
-
if (typeof
|
|
2840
|
+
if (typeof vRoundingMode === "function") {
|
|
2509
2841
|
// Support custom function for rounding the number
|
|
2510
|
-
|
|
2842
|
+
vValue = vRoundingMode(vValue, iMaxFractionDigits);
|
|
2511
2843
|
} else {
|
|
2512
2844
|
// The NumberFormat.RoundingMode had all values in lower case before and later changed all values to upper case
|
|
2513
2845
|
// to match the key according to the UI5 guideline for defining enum. Therefore it's needed to support both
|
|
2514
2846
|
// lower and upper cases. Here checks whether the value has only lower case letters and converts it all to upper
|
|
2515
2847
|
// case if so.
|
|
2516
|
-
if (
|
|
2517
|
-
|
|
2518
|
-
}
|
|
2519
|
-
if (!iMaxFractionDigits) {
|
|
2520
|
-
return mRoundingFunction[sRoundingMode](fValue);
|
|
2848
|
+
if (vRoundingMode.match(/^[a-z_]+$/)) {
|
|
2849
|
+
vRoundingMode = vRoundingMode.toUpperCase();
|
|
2521
2850
|
}
|
|
2522
2851
|
|
|
2523
|
-
//
|
|
2524
|
-
|
|
2525
|
-
//
|
|
2526
|
-
|
|
2527
|
-
//
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
}
|
|
2533
|
-
return
|
|
2852
|
+
// 1. Move the decimal point to right by maxFactionDigits; e.g. 1.005 with maxFractionDigits 2 => 100.5
|
|
2853
|
+
vValue = NumberFormat._shiftDecimalPoint(vValue, iMaxFractionDigits, true);
|
|
2854
|
+
// 2. Use the rounding function to round the first digit after decimal point; e.g. ceil(100.5) => 101
|
|
2855
|
+
vValue = mRoundingFunction[vRoundingMode](vValue);
|
|
2856
|
+
// 3. Finally move the decimal point back to the original position; e.g. by 2 digits => 1.01
|
|
2857
|
+
vValue = NumberFormat._shiftDecimalPoint(vValue, -iMaxFractionDigits, true);
|
|
2858
|
+
if (typeof vValue === "string") {
|
|
2859
|
+
vValue = vValue.replace(rRemoveMinusFromZero, "$1");
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
return vValue;
|
|
2534
2863
|
}
|
|
2535
2864
|
function quote(sRegex) {
|
|
2536
2865
|
return sRegex.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
|
|
@@ -2588,7 +2917,7 @@ function parseNumberAndUnit(mUnitPatterns, sValue, bShowNumber, sLanguageTag) {
|
|
|
2588
2917
|
if (!sKey.startsWith("unitPattern")) {
|
|
2589
2918
|
continue;
|
|
2590
2919
|
}
|
|
2591
|
-
sUnitPattern = mUnitPatterns[sUnitCode][sKey];
|
|
2920
|
+
sUnitPattern = FormatUtils.normalize(mUnitPatterns[sUnitCode][sKey]);
|
|
2592
2921
|
|
|
2593
2922
|
// IMPORTANT:
|
|
2594
2923
|
// To increase performance we are using native string operations instead of regex,
|
|
@@ -2711,7 +3040,7 @@ function findLongestMatch(sValue, mCollection, bCaseInsensitive) {
|
|
|
2711
3040
|
if (!sCurSymbol) {
|
|
2712
3041
|
continue;
|
|
2713
3042
|
}
|
|
2714
|
-
sCurSymbol =
|
|
3043
|
+
sCurSymbol = FormatUtils.normalize(sCurSymbol);
|
|
2715
3044
|
if (sValue.indexOf(sCurSymbol) >= 0 && sSymbol.length <= sCurSymbol.length) {
|
|
2716
3045
|
sCode = sCurCode;
|
|
2717
3046
|
bDuplicate = false;
|
|
@@ -2719,7 +3048,7 @@ function findLongestMatch(sValue, mCollection, bCaseInsensitive) {
|
|
|
2719
3048
|
sSymbol = sCurSymbol;
|
|
2720
3049
|
sRecognizedCurrency = sCurSymbol;
|
|
2721
3050
|
} else if (bCaseInsensitive) {
|
|
2722
|
-
sLanguageTag =
|
|
3051
|
+
sLanguageTag = Localization.getLanguageTag().toString();
|
|
2723
3052
|
sCurSymbolToUpperCase = sCurSymbol.toLocaleUpperCase(sLanguageTag);
|
|
2724
3053
|
iIndex = sValue.toLocaleUpperCase(sLanguageTag).indexOf(sCurSymbolToUpperCase);
|
|
2725
3054
|
if (iIndex >= 0) {
|
|
@@ -2768,7 +3097,7 @@ function findLongestMatch(sValue, mCollection, bCaseInsensitive) {
|
|
|
2768
3097
|
*/
|
|
2769
3098
|
function parseNumberAndCurrency(oConfig) {
|
|
2770
3099
|
var aIsoMatches,
|
|
2771
|
-
sValue = oConfig.value
|
|
3100
|
+
sValue = oConfig.value;
|
|
2772
3101
|
|
|
2773
3102
|
// Search for known symbols (longest match)
|
|
2774
3103
|
// no distinction between default and custom currencies
|
|
@@ -2782,7 +3111,7 @@ function parseNumberAndCurrency(oConfig) {
|
|
|
2782
3111
|
if (!oMatch.code && !oConfig.customCurrenciesAvailable) {
|
|
2783
3112
|
// Match 3-letter iso code
|
|
2784
3113
|
aIsoMatches = sValue.match(/(^[A-Z]{3}|[A-Z]{3}$)/i);
|
|
2785
|
-
oMatch.code = aIsoMatches && aIsoMatches[0].toLocaleUpperCase(
|
|
3114
|
+
oMatch.code = aIsoMatches && aIsoMatches[0].toLocaleUpperCase(Localization.getLanguageTag().toString());
|
|
2786
3115
|
oMatch.recognizedCurrency = aIsoMatches && aIsoMatches[0];
|
|
2787
3116
|
}
|
|
2788
3117
|
}
|