Skip to content

Commit

Permalink
fix(android): formatToParts() on Android 4.4
Browse files Browse the repository at this point in the history
  • Loading branch information
jquick-axway authored and sgtcoolguy committed Jul 21, 2020
1 parent a7307f9 commit 2a2f0dc
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package ti.modules.titanium.locale;

import java.text.AttributedCharacterIterator;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.Format;
Expand Down Expand Up @@ -197,49 +198,41 @@ public String format(Date date)
public KrollDict[] formatToParts(Date value)
{
// Format date to a string buffer and obtain all of its field positions.
StringBuffer stringBuffer = new StringBuffer(64);
FieldPosition[] fieldPositionArray = new FieldPosition[] {
new FieldPosition(DateFormat.Field.AM_PM),
new FieldPosition(DateFormat.Field.DAY_OF_MONTH),
new FieldPosition(DateFormat.Field.DAY_OF_WEEK),
new FieldPosition(DateFormat.Field.DAY_OF_WEEK_IN_MONTH),
new FieldPosition(DateFormat.Field.ERA),
new FieldPosition(DateFormat.Field.HOUR0),
new FieldPosition(DateFormat.Field.HOUR1),
new FieldPosition(DateFormat.Field.HOUR_OF_DAY0),
new FieldPosition(DateFormat.Field.HOUR_OF_DAY1),
new FieldPosition(DateFormat.Field.MILLISECOND),
new FieldPosition(DateFormat.Field.MINUTE),
new FieldPosition(DateFormat.Field.MONTH),
new FieldPosition(DateFormat.Field.SECOND),
new FieldPosition(DateFormat.Field.TIME_ZONE),
new FieldPosition(DateFormat.Field.YEAR)
};
StringBuilder stringBuilder = new StringBuilder(64);
HashMap<Integer, FieldPosition> fieldPositionIndexMap = new HashMap<>();
for (FieldPosition fieldPosition : fieldPositionArray) {
// Fetch the next field position by formatting date to string.
// Unfortunately, we have to recreate string every time. There's no way to do this in one shot.
stringBuffer.delete(0, stringBuffer.length());
this.dateFormat.format(value, stringBuffer, fieldPosition);

// Add field to map if it exists in string.
int beginIndex = fieldPosition.getBeginIndex();
if ((beginIndex >= 0) && (beginIndex != fieldPosition.getEndIndex())) {
fieldPositionIndexMap.put(beginIndex, fieldPosition);
AttributedCharacterIterator charIter = this.dateFormat.formatToCharacterIterator(value);
for (char nextChar = charIter.first(); nextChar != charIter.DONE; nextChar = charIter.next()) {
stringBuilder.append(nextChar);
for (Map.Entry<AttributedCharacterIterator.Attribute, Object> entry : charIter.getAttributes().entrySet()) {
// Skip attributes that are not format fields.
if (!(entry.getKey() instanceof Format.Field)) {
continue;
}

// Add field position to map if not done already.
Format.Field formatField = (Format.Field) entry.getKey();
int beginIndex = charIter.getRunStart(formatField);
if ((beginIndex >= 0) && !fieldPositionIndexMap.containsKey(beginIndex)) {
FieldPosition fieldPosition = new FieldPosition(formatField);
fieldPosition.setBeginIndex(beginIndex);
fieldPosition.setEndIndex(charIter.getRunLimit(formatField));
fieldPositionIndexMap.put(beginIndex, fieldPosition);
}
}
}
String stringValue = stringBuilder.toString();

// Create the parts list.
ArrayList<KrollDict> partList = new ArrayList<>(32);
for (int index = 0; index < stringBuffer.length();) {
for (int index = 0; index < stringValue.length();) {
String typeName = null;
String substring = null;

// Fetch the next field.
FieldPosition fieldPosition = fieldPositionIndexMap.get(index);
if (fieldPosition != null) {
// Extract the field's string.
substring = stringBuffer.substring(fieldPosition.getBeginIndex(), fieldPosition.getEndIndex());
substring = stringValue.substring(fieldPosition.getBeginIndex(), fieldPosition.getEndIndex());

// Get the JavaScript "Intl.DateTimeFormat" part type equivalent.
Format.Field formatField = fieldPosition.getFieldAttribute();
Expand Down Expand Up @@ -281,8 +274,8 @@ public KrollDict[] formatToParts(Date value)

// Extract all of the characters up to the next field or end of string.
int endIndex = index;
for (; (endIndex < stringBuffer.length()) && !fieldPositionIndexMap.containsKey(endIndex); endIndex++);
substring = stringBuffer.substring(index, endIndex);
for (; (endIndex < stringValue.length()) && !fieldPositionIndexMap.containsKey(endIndex); endIndex++);
substring = stringValue.substring(index, endIndex);

// Update index past this literal substring.
index = endIndex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.AttributedCharacterIterator;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.FieldPosition;
Expand Down Expand Up @@ -198,34 +199,36 @@ public KrollDict[] formatToParts(double value)
value = BigDecimal.valueOf(value).round(this.maxSignificantDigitsContext).doubleValue();
}

// Format value to a string buffer and obtain all of its field positions.
// Note: Skip fetching the "GROUPING_SEPARATOR" field since it can't fetch more than one separator.
StringBuffer stringBuffer = new StringBuffer(64);
FieldPosition[] fieldPositionArray = new FieldPosition[] {
new FieldPosition(NumberFormat.Field.CURRENCY),
new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR),
new FieldPosition(NumberFormat.Field.EXPONENT),
new FieldPosition(NumberFormat.Field.EXPONENT_SIGN),
new FieldPosition(NumberFormat.Field.EXPONENT_SYMBOL),
new FieldPosition(NumberFormat.Field.FRACTION),
new FieldPosition(NumberFormat.Field.INTEGER),
new FieldPosition(NumberFormat.Field.PERCENT),
new FieldPosition(NumberFormat.Field.PERMILLE),
new FieldPosition(NumberFormat.Field.SIGN)
};
// Format value to a string and obtain all of its field positions.
StringBuilder stringBuilder = new StringBuilder(64);
HashMap<Integer, FieldPosition> fieldPositionIndexMap = new HashMap<>();
for (FieldPosition fieldPosition : fieldPositionArray) {
// Fetch the next field position by formatting value to string.
// Unfortunately, we have to recreate string every time. There's no way to do this in one shot.
stringBuffer.delete(0, stringBuffer.length());
this.numberFormat.format(value, stringBuffer, fieldPosition);
AttributedCharacterIterator charIter = this.numberFormat.formatToCharacterIterator(value);
for (char nextChar = charIter.first(); nextChar != charIter.DONE; nextChar = charIter.next()) {
stringBuilder.append(nextChar);
for (Map.Entry<AttributedCharacterIterator.Attribute, Object> entry : charIter.getAttributes().entrySet()) {
// Skip attributes that are not format fields.
if (!(entry.getKey() instanceof Format.Field)) {
continue;
}

// Skip "GROUPING_SEPARATOR" fields since they overlap "INTEGER" fields.
// We'll split these fields to substrings later.
Format.Field formatField = (Format.Field) entry.getKey();
if (formatField.equals(NumberFormat.Field.GROUPING_SEPARATOR)) {
continue;
}

// Add field to map if it exists in string.
int beginIndex = fieldPosition.getBeginIndex();
if ((beginIndex >= 0) && (beginIndex != fieldPosition.getEndIndex())) {
fieldPositionIndexMap.put(beginIndex, fieldPosition);
// Add field position to map if not done already.
int beginIndex = charIter.getRunStart(formatField);
if ((beginIndex >= 0) && !fieldPositionIndexMap.containsKey(beginIndex)) {
FieldPosition fieldPosition = new FieldPosition(formatField);
fieldPosition.setBeginIndex(beginIndex);
fieldPosition.setEndIndex(charIter.getRunLimit(formatField));
fieldPositionIndexMap.put(beginIndex, fieldPosition);
}
}
}
String stringValue = stringBuilder.toString();

// Fetch the localized symbols used by this formatter.
DecimalFormatSymbols symbols = null;
Expand All @@ -240,15 +243,15 @@ public KrollDict[] formatToParts(double value)

// Create the parts list.
ArrayList<KrollDict> partList = new ArrayList<>(32);
for (int index = 0; index < stringBuffer.length();) {
for (int index = 0; index < stringValue.length();) {
String typeName = null;
String substring = null;

// Fetch the next field.
FieldPosition fieldPosition = fieldPositionIndexMap.get(index);
if (fieldPosition != null) {
// Extract the field's string.
substring = stringBuffer.substring(fieldPosition.getBeginIndex(), fieldPosition.getEndIndex());
substring = stringValue.substring(fieldPosition.getBeginIndex(), fieldPosition.getEndIndex());

// Get the JavaScript "Intl.NumberFormat" part type equivalent.
Format.Field formatField = fieldPosition.getFieldAttribute();
Expand Down Expand Up @@ -291,8 +294,8 @@ public KrollDict[] formatToParts(double value)

// Extract all of the characters up to the next field or end of string.
int endIndex = index;
for (; (endIndex < stringBuffer.length()) && !fieldPositionIndexMap.containsKey(endIndex); endIndex++);
substring = stringBuffer.substring(index, endIndex);
for (; (endIndex < stringValue.length()) && !fieldPositionIndexMap.containsKey(endIndex); endIndex++);
substring = stringValue.substring(index, endIndex);

// Update index past this literal substring.
index = endIndex;
Expand Down

0 comments on commit 2a2f0dc

Please sign in to comment.