Skip to content

Commit 9500ea2

Browse files
committed
Support ICU 62+
- ICU 62.1 icu4c DecimalFormat api now wraps the new NumberFormatter api. - Update currency spacing accoring to ICU changes (http://bugs.icu-project.org/trac/ticket/6560) - Disable tests that allowed different patterns for negative numbers, http://icu-project.org/apiref/icu4c/classDecimalFormat.html states that negative patterns serve only to specify the negative prefix and suffix. The number of digits, minimal digits and other characteristics are ignored in the negative subpattern. Support for different negative patterns may need to be added as a workaround.
1 parent 10dfaf5 commit 9500ea2

File tree

2 files changed

+34
-15
lines changed

2 files changed

+34
-15
lines changed

CoreFoundation/Locale.subproj/CFNumberFormatter.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,16 @@ CFNumberFormatterRef CFNumberFormatterCreate(CFAllocatorRef allocator, CFLocaleR
136136
}
137137

138138
if (kCFNumberFormatterNoStyle == style) {
139+
#if U_ICU_VERSION_MAJOR_NUM < 62
140+
// ICU62+ is stricter about patterns matching attribute settings and setting UNUM_MAX_INTEGER_DIGITS = 42 would result in a pattern of 42x '#' not 1x '#' as is set here.
139141
UChar ubuff[1];
140142
status = U_ZERO_ERROR;
141143
ubuff[0] = '#';
142144

143145
__cficu_unum_applyPattern(memory->_nf, false, ubuff, 1, NULL, &status);
144146
__cficu_unum_setAttribute(memory->_nf, UNUM_MAX_INTEGER_DIGITS, 42);
145147
__cficu_unum_setAttribute(memory->_nf, UNUM_MAX_FRACTION_DIGITS, 0);
148+
#endif
146149
}
147150
//Prior to Gala, CFLocaleCreateCopy() always just retained. This caused problems because CFLocaleGetValue(locale, kCFLocaleCalendarKey) would create a calendar, then set its locale to self, leading to a retain cycle
148151
//Since we're not in that situation here, and this is a frequently used path, we retain as we used to

TestFoundation/TestNumberFormatter.swift

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@
1010

1111
class TestNumberFormatter: XCTestCase {
1212

13+
var currencySpacing = ""
14+
#if !canImport(Darwin)
15+
// This awfulness is needed until the non-Darwin versions are always using ICU >= 64 at which
16+
// time the currenySpacing can be set to "\u{00A0}". This is just a way to allow the tests
17+
// to run on Linux with both older and current ICU
18+
override func setUp() {
19+
super.setUp()
20+
21+
let numberFormatter = NumberFormatter()
22+
numberFormatter.numberStyle = .currency
23+
numberFormatter.currencyCode = "T"
24+
currencySpacing = String((numberFormatter.string(from: 1)!.dropFirst().dropLast(4)))
25+
}
26+
#endif
27+
1328
func test_defaultPropertyValues() {
1429
let numberFormatter = NumberFormatter()
1530
XCTAssertEqual(numberFormatter.numberStyle, .none)
@@ -195,14 +210,14 @@ class TestNumberFormatter: XCTestCase {
195210
XCTAssertEqual(numberFormatter.maximumSignificantDigits, 6)
196211
XCTAssertEqual(numberFormatter.usesSignificantDigits, false)
197212
XCTAssertEqual(numberFormatter.formatWidth, 0)
198-
XCTAssertEqual(numberFormatter.format, "¤¤#,##0.00;USD0.00;¤¤#,##0.00")
213+
XCTAssertEqual(numberFormatter.format, "¤¤#,##0.00;USD\(currencySpacing)0.00;¤¤#,##0.00")
199214
XCTAssertEqual(numberFormatter.positiveFormat, "¤¤#,##0.00")
200215
XCTAssertEqual(numberFormatter.negativeFormat, "¤¤#,##0.00")
201216
XCTAssertNil(numberFormatter.multiplier)
202217
XCTAssertTrue(numberFormatter.usesGroupingSeparator)
203218
XCTAssertEqual(numberFormatter.groupingSize, 3)
204219
XCTAssertEqual(numberFormatter.secondaryGroupingSize, 0)
205-
XCTAssertEqual(numberFormatter.string(from: NSNumber(1234567890)), "USD1,234,567,890.00")
220+
XCTAssertEqual(numberFormatter.string(from: NSNumber(1234567890)), "USD\(currencySpacing)1,234,567,890.00")
206221
}
207222

208223
func test_defaultCurrencyPluralPropertyValues() {
@@ -262,12 +277,12 @@ class TestNumberFormatter: XCTestCase {
262277
XCTAssertEqual(numberFormatter.string(from: -1.1), "-£1.10")
263278

264279
numberFormatter.currencyCode = "T"
265-
XCTAssertEqual(numberFormatter.format, "¤#,##0.00;T0.00;¤#,##0.00")
280+
XCTAssertEqual(numberFormatter.format, "¤#,##0.00;T\(currencySpacing)0.00;¤#,##0.00")
266281
numberFormatter.currencyDecimalSeparator = "_"
267-
XCTAssertEqual(numberFormatter.format, "¤#,##0.00;T0_00;¤#,##0.00")
282+
XCTAssertEqual(numberFormatter.format, "¤#,##0.00;T\(currencySpacing)0_00;¤#,##0.00")
268283

269284
let formattedString = numberFormatter.string(from: 42)
270-
XCTAssertEqual(formattedString, "T42_00")
285+
XCTAssertEqual(formattedString, "T\(currencySpacing)42_00")
271286
}
272287

273288
func test_decimalSeparator() {
@@ -289,9 +304,9 @@ class TestNumberFormatter: XCTestCase {
289304
numberFormatter.numberStyle = .currency
290305
numberFormatter.currencyDecimalSeparator = "-"
291306
numberFormatter.currencyCode = "T"
292-
XCTAssertEqual(numberFormatter.format, "¤#,##0.00;T0-00;¤#,##0.00")
307+
XCTAssertEqual(numberFormatter.format, "¤#,##0.00;T\(currencySpacing)0-00;¤#,##0.00")
293308
let formattedString = numberFormatter.string(from: 42.42)
294-
XCTAssertEqual(formattedString, "T42-42")
309+
XCTAssertEqual(formattedString, "T\(currencySpacing)42-42")
295310
}
296311

297312
func test_alwaysShowDecimalSeparator() {
@@ -623,18 +638,18 @@ class TestNumberFormatter: XCTestCase {
623638
XCTAssertEqual(formatter.minimumIntegerDigits, 0)
624639
formatter.locale = Locale(identifier: "en_US")
625640
XCTAssertEqual(formatter.string(from: 0), "USD.00")
626-
XCTAssertEqual(formatter.string(from: 1.23), "USD1.23")
627-
XCTAssertEqual(formatter.string(from: 123.4), "USD123.40")
641+
XCTAssertEqual(formatter.string(from: 1.23), "USD\(currencySpacing)1.23")
642+
XCTAssertEqual(formatter.string(from: 123.4), "USD\(currencySpacing)123.40")
628643

629644
// If .minimumIntegerDigits is not set before .numberStyle change, update the value
630645
let formatter2 = NumberFormatter()
631646
XCTAssertEqual(formatter2.minimumIntegerDigits, 0)
632647
formatter2.numberStyle = .currencyISOCode
633648
XCTAssertEqual(formatter2.minimumIntegerDigits, 1)
634649
formatter2.locale = Locale(identifier: "en_US")
635-
XCTAssertEqual(formatter2.string(from: 0.01), "USD0.01")
636-
XCTAssertEqual(formatter2.string(from: 1.234), "USD1.23")
637-
XCTAssertEqual(formatter2.string(from: 123456.7), "USD123,456.70")
650+
XCTAssertEqual(formatter2.string(from: 0.01), "USD\(currencySpacing)0.01")
651+
XCTAssertEqual(formatter2.string(from: 1.234), "USD\(currencySpacing)1.23")
652+
XCTAssertEqual(formatter2.string(from: 123456.7), "USD\(currencySpacing)123,456.70")
638653
}
639654

640655
func test_currencyAccountingMinimumIntegerDigits() {
@@ -663,6 +678,7 @@ class TestNumberFormatter: XCTestCase {
663678
func test_maximumIntegerDigits() {
664679
let numberFormatter = NumberFormatter()
665680
numberFormatter.maximumIntegerDigits = 3
681+
numberFormatter.minimumIntegerDigits = 3
666682
let formattedString = numberFormatter.string(from: 1_000)
667683
XCTAssertEqual(formattedString, "000")
668684
}
@@ -790,7 +806,7 @@ class TestNumberFormatter: XCTestCase {
790806
numberFormatter.currencyCode = "T"
791807
numberFormatter.currencyDecimalSeparator = "/"
792808
let formattedString = numberFormatter.string(from: 42_000)
793-
XCTAssertEqual(formattedString, "T42_000/00")
809+
XCTAssertEqual(formattedString, "T\(currencySpacing)42_000/00")
794810

795811
}
796812

@@ -1127,8 +1143,8 @@ class TestNumberFormatter: XCTestCase {
11271143
XCTAssertEqual(formatter.string(from: NSNumber(value: Double.pi)), "3.14159")
11281144

11291145
formatter = NumberFormatter()
1130-
formatter.negativeFormat = "#.#########"
11311146
formatter.positiveFormat = "#.#########"
1147+
formatter.negativeFormat = "-#.#########"
11321148
XCTAssertEqual(formatter.string(from: NSNumber(value: 0.5)), "0.5")
11331149
XCTAssertEqual(formatter.string(from: NSNumber(value: -0.5)), "-0.5")
11341150
}
@@ -1206,7 +1222,7 @@ class TestNumberFormatter: XCTestCase {
12061222
("test_en_US_initialValues", test_en_US_initialValues),
12071223
("test_pt_BR_initialValues", test_pt_BR_initialValues),
12081224
("test_changingLocale", test_changingLocale),
1209-
("test_settingFormat", test_settingFormat),
1225+
/* ⚠️ */ ("test_settingFormat", testExpectedToFail(test_settingFormat), "Mostly broken with ICU62+"),
12101226
("test_usingFormat", test_usingFormat),
12111227
("test_propertyChanges", test_propertyChanges),
12121228
]

0 commit comments

Comments
 (0)