8066806: java.time.format.DateTimeFormatter cannot parse an offset with single digit hour

Added support for single digit hour in offset

Reviewed-by: rriggs, scolebourne
This commit is contained in:
Nadeesh TV 2016-07-28 10:28:21 +00:00
parent 82e9d18d0e
commit f7eff31b47
5 changed files with 907 additions and 54 deletions

View File

@ -928,7 +928,24 @@ public final class DateTimeFormatterBuilder {
* second if non-zero, no colon
* <li>{@code +HH:mm:ss} - hour, with minute if non-zero or with minute and
* second if non-zero, with colon
* <li>{@code +H} - hour only, ignoring minute and second
* <li>{@code +Hmm} - hour, with minute if non-zero, ignoring second, no colon
* <li>{@code +H:mm} - hour, with minute if non-zero, ignoring second, with colon
* <li>{@code +HMM} - hour and minute, ignoring second, no colon
* <li>{@code +H:MM} - hour and minute, ignoring second, with colon
* <li>{@code +HMMss} - hour and minute, with second if non-zero, no colon
* <li>{@code +H:MM:ss} - hour and minute, with second if non-zero, with colon
* <li>{@code +HMMSS} - hour, minute and second, no colon
* <li>{@code +H:MM:SS} - hour, minute and second, with colon
* <li>{@code +Hmmss} - hour, with minute if non-zero or with minute and
* second if non-zero, no colon
* <li>{@code +H:mm:ss} - hour, with minute if non-zero or with minute and
* second if non-zero, with colon
* </ul>
* Patterns containing "HH" will format and parse a two digit hour,
* zero-padded if necessary. Patterns containing "H" will format with no
* zero-padding, and parse either one or two digits.
* In lenient mode, the parser will be greedy and parse the maximum digits possible.
* The "no offset" text controls what text is printed when the total amount of
* the offset fields to be output is zero.
* Example values would be 'Z', '+00:00', 'UTC' or 'GMT'.
@ -3475,13 +3492,15 @@ public final class DateTimeFormatterBuilder {
*/
static final class OffsetIdPrinterParser implements DateTimePrinterParser {
static final String[] PATTERNS = new String[] {
"+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
"+HH", "+HHmm", "+HH:mm", "+HHMM", "+HH:MM", "+HHMMss", "+HH:MM:ss", "+HHMMSS", "+HH:MM:SS", "+HHmmss", "+HH:mm:ss",
"+H", "+Hmm", "+H:mm", "+HMM", "+H:MM", "+HMMss", "+H:MM:ss", "+HMMSS", "+H:MM:SS", "+Hmmss", "+H:mm:ss",
}; // order used in pattern builder
static final OffsetIdPrinterParser INSTANCE_ID_Z = new OffsetIdPrinterParser("+HH:MM:ss", "Z");
static final OffsetIdPrinterParser INSTANCE_ID_ZERO = new OffsetIdPrinterParser("+HH:MM:ss", "0");
private final String noOffsetText;
private final int type;
private final int style;
/**
* Constructor.
@ -3493,6 +3512,7 @@ public final class DateTimeFormatterBuilder {
Objects.requireNonNull(pattern, "pattern");
Objects.requireNonNull(noOffsetText, "noOffsetText");
this.type = checkPattern(pattern);
this.style = type % 11;
this.noOffsetText = noOffsetText;
}
@ -3505,6 +3525,14 @@ public final class DateTimeFormatterBuilder {
throw new IllegalArgumentException("Invalid zone offset pattern: " + pattern);
}
private boolean isPaddedHour() {
return type < 11;
}
private boolean isColon() {
return style > 0 && (style % 2) == 0;
}
@Override
public boolean format(DateTimePrintContext context, StringBuilder buf) {
Long offsetSecs = context.getValue(OFFSET_SECONDS);
@ -3520,15 +3548,17 @@ public final class DateTimeFormatterBuilder {
int absSeconds = Math.abs(totalSecs % 60);
int bufPos = buf.length();
int output = absHours;
buf.append(totalSecs < 0 ? "-" : "+")
.append((char) (absHours / 10 + '0')).append((char) (absHours % 10 + '0'));
if ((type >= 3 && type < 9) || (type >= 9 && absSeconds > 0) || (type >= 1 && absMinutes > 0)) {
buf.append((type % 2) == 0 ? ":" : "")
.append((char) (absMinutes / 10 + '0')).append((char) (absMinutes % 10 + '0'));
buf.append(totalSecs < 0 ? "-" : "+");
if (isPaddedHour() || absHours >= 10) {
formatZeroPad(false, absHours, buf);
} else {
buf.append((char) (absHours + '0'));
}
if ((style >= 3 && style <= 8) || (style >= 9 && absSeconds > 0) || (style >= 1 && absMinutes > 0)) {
formatZeroPad(isColon(), absMinutes, buf);
output += absMinutes;
if (type == 7 || type == 8 || (type >= 5 && absSeconds > 0)) {
buf.append((type % 2) == 0 ? ":" : "")
.append((char) (absSeconds / 10 + '0')).append((char) (absSeconds % 10 + '0'));
if (style == 7 || style == 8 || (style >= 5 && absSeconds > 0)) {
formatZeroPad(isColon(), absSeconds, buf);
output += absSeconds;
}
}
@ -3540,19 +3570,16 @@ public final class DateTimeFormatterBuilder {
return true;
}
private void formatZeroPad(boolean colon, int value, StringBuilder buf) {
buf.append(colon ? ":" : "")
.append((char) (value / 10 + '0'))
.append((char) (value % 10 + '0'));
}
@Override
public int parse(DateTimeParseContext context, CharSequence text, int position) {
int length = text.length();
int noOffsetLen = noOffsetText.length();
int parseType = type;
if (context.isStrict() == false) {
if ((parseType > 0 && (parseType % 2) == 0) ||
(parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
parseType = 10;
} else {
parseType = 9;
}
}
if (noOffsetLen == 0) {
if (position == length) {
return context.setParsedField(OFFSET_SECONDS, 0, position, position);
@ -3571,12 +3598,87 @@ public final class DateTimeFormatterBuilder {
if (sign == '+' || sign == '-') {
// starts
int negative = (sign == '-' ? -1 : 1);
boolean isColon = isColon();
boolean paddedHour = isPaddedHour();
int[] array = new int[4];
array[0] = position + 1;
if ((parseNumber(array, 1, text, true, parseType) ||
parseNumber(array, 2, text, parseType >= 3 && parseType < 9, parseType) ||
parseNumber(array, 3, text, parseType == 7 || parseType == 8, parseType)) == false) {
// success
int parseType = type;
// select parse type when lenient
if (!context.isStrict()) {
if (paddedHour) {
if (isColon || (parseType == 0 && length > position + 3 && text.charAt(position + 3) == ':')) {
isColon = true; // needed in cases like ("+HH", "+01:01")
parseType = 10;
} else {
parseType = 9;
}
} else {
if (isColon || (parseType == 11 && length > position + 3 && (text.charAt(position + 2) == ':' || text.charAt(position + 3) == ':'))) {
isColon = true;
parseType = 21; // needed in cases like ("+H", "+1:01")
} else {
parseType = 20;
}
}
}
// parse according to the selected pattern
switch (parseType) {
case 0: // +HH
case 11: // +H
parseHour(text, paddedHour, array);
break;
case 1: // +HHmm
case 2: // +HH:mm
case 13: // +H:mm
parseHour(text, paddedHour, array);
parseMinute(text, isColon, false, array);
break;
case 3: // +HHMM
case 4: // +HH:MM
case 15: // +H:MM
parseHour(text, paddedHour, array);
parseMinute(text, isColon, true, array);
break;
case 5: // +HHMMss
case 6: // +HH:MM:ss
case 17: // +H:MM:ss
parseHour(text, paddedHour, array);
parseMinute(text, isColon, true, array);
parseSecond(text, isColon, false, array);
break;
case 7: // +HHMMSS
case 8: // +HH:MM:SS
case 19: // +H:MM:SS
parseHour(text, paddedHour, array);
parseMinute(text, isColon, true, array);
parseSecond(text, isColon, true, array);
break;
case 9: // +HHmmss
case 10: // +HH:mm:ss
case 21: // +H:mm:ss
parseHour(text, paddedHour, array);
parseOptionalMinuteSecond(text, isColon, array);
break;
case 12: // +Hmm
parseVariableWidthDigits(text, 1, 4, array);
break;
case 14: // +HMM
parseVariableWidthDigits(text, 3, 4, array);
break;
case 16: // +HMMss
parseVariableWidthDigits(text, 3, 6, array);
break;
case 18: // +HMMSS
parseVariableWidthDigits(text, 5, 6, array);
break;
case 20: // +Hmmss
parseVariableWidthDigits(text, 1, 6, array);
break;
}
if (array[0] > 0) {
if (array[1] > 23 || array[2] > 59 || array[3] > 59) {
throw new DateTimeException("Value out of range: Hour[0-23], Minute[0-59], Second[0-59]");
}
long offsetSecs = negative * (array[1] * 3600L + array[2] * 60L + array[3]);
return context.setParsedField(OFFSET_SECONDS, offsetSecs, position, array[0]);
}
@ -3588,42 +3690,118 @@ public final class DateTimeFormatterBuilder {
return ~position;
}
/**
* Parse a two digit zero-prefixed number.
*
* @param array the array of parsed data, 0=pos,1=hours,2=mins,3=secs, not null
* @param arrayIndex the index to parse the value into
* @param parseText the offset ID, not null
* @param required whether this number is required
* @param parseType the offset pattern type
* @return true if an error occurred
*/
private boolean parseNumber(int[] array, int arrayIndex, CharSequence parseText, boolean required, int parseType) {
if ((parseType + 3) / 2 < arrayIndex) {
return false; // ignore seconds/minutes
private void parseHour(CharSequence parseText, boolean paddedHour, int[] array) {
if (paddedHour) {
// parse two digits
if (!parseDigits(parseText, false, 1, array)) {
array[0] = ~array[0];
}
} else {
// parse one or two digits
parseVariableWidthDigits(parseText, 1, 2, array);
}
}
private void parseMinute(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
if (!parseDigits(parseText, isColon, 2, array)) {
if (mandatory) {
array[0] = ~array[0];
}
}
}
private void parseSecond(CharSequence parseText, boolean isColon, boolean mandatory, int[] array) {
if (!parseDigits(parseText, isColon, 3, array)) {
if (mandatory) {
array[0] = ~array[0];
}
}
}
private void parseOptionalMinuteSecond(CharSequence parseText, boolean isColon, int[] array) {
if (parseDigits(parseText, isColon, 2, array)) {
parseDigits(parseText, isColon, 3, array);
}
}
private boolean parseDigits(CharSequence parseText, boolean isColon, int arrayIndex, int[] array) {
int pos = array[0];
if ((parseType % 2) == 0 && arrayIndex > 1) {
if (pos < 0) {
return true;
}
if (isColon && arrayIndex != 1) { // ':' will precede only in case of minute/second
if (pos + 1 > parseText.length() || parseText.charAt(pos) != ':') {
return required;
return false;
}
pos++;
}
if (pos + 2 > parseText.length()) {
return required;
return false;
}
char ch1 = parseText.charAt(pos++);
char ch2 = parseText.charAt(pos++);
if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') {
return required;
return false;
}
int value = (ch1 - 48) * 10 + (ch2 - 48);
if (value < 0 || value > 59) {
return required;
return false;
}
array[arrayIndex] = value;
array[0] = pos;
return false;
return true;
}
private void parseVariableWidthDigits(CharSequence parseText, int minDigits, int maxDigits, int[] array) {
// scan the text to find the available number of digits up to maxDigits
// so long as the number available is minDigits or more, the input is valid
// then parse the number of available digits
int pos = array[0];
int available = 0;
char[] chars = new char[maxDigits];
for (int i = 0; i < maxDigits; i++) {
if (pos + 1 > parseText.length()) {
break;
}
char ch = parseText.charAt(pos++);
if (ch < '0' || ch > '9') {
pos--;
break;
}
chars[i] = ch;
available++;
}
if (available < minDigits) {
array[0] = ~array[0];
return;
}
switch (available) {
case 1:
array[1] = (chars[0] - 48);
break;
case 2:
array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
break;
case 3:
array[1] = (chars[0] - 48);
array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
break;
case 4:
array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
break;
case 5:
array[1] = (chars[0] - 48);
array[2] = ((chars[1] - 48) * 10 + (chars[2] - 48));
array[3] = ((chars[3] - 48) * 10 + (chars[4] - 48));
break;
case 6:
array[1] = ((chars[0] - 48) * 10 + (chars[1] - 48));
array[2] = ((chars[2] - 48) * 10 + (chars[3] - 48));
array[3] = ((chars[4] - 48) * 10 + (chars[5] - 48));
break;
}
array[0] = pos;
}
@Override

View File

@ -407,6 +407,127 @@ public class TCKDateTimeFormatterBuilder {
{"+HH:mm:ss", 2, 0, 45, "+02:00:45"},
{"+HH:mm:ss", 2, 30, 45, "+02:30:45"},
{"+H", 2, 0, 0, "+2"},
{"+H", -2, 0, 0, "-2"},
{"+H", 2, 30, 0, "+2"},
{"+H", 2, 0, 45, "+2"},
{"+H", 2, 30, 45, "+2"},
{"+H", 12, 0, 0, "+12"},
{"+H", -12, 0, 0, "-12"},
{"+H", 12, 30, 0, "+12"},
{"+H", 12, 0, 45, "+12"},
{"+H", 12, 30, 45, "+12"},
{"+Hmm", 2, 0, 0, "+2"},
{"+Hmm", -2, 0, 0, "-2"},
{"+Hmm", 2, 30, 0, "+230"},
{"+Hmm", 2, 0, 45, "+2"},
{"+Hmm", 2, 30, 45, "+230"},
{"+Hmm", 12, 0, 0, "+12"},
{"+Hmm", -12, 0, 0, "-12"},
{"+Hmm", 12, 30, 0, "+1230"},
{"+Hmm", 12, 0, 45, "+12"},
{"+Hmm", 12, 30, 45, "+1230"},
{"+H:mm", 2, 0, 0, "+2"},
{"+H:mm", -2, 0, 0, "-2"},
{"+H:mm", 2, 30, 0, "+2:30"},
{"+H:mm", 2, 0, 45, "+2"},
{"+H:mm", 2, 30, 45, "+2:30"},
{"+H:mm", 12, 0, 0, "+12"},
{"+H:mm", -12, 0, 0, "-12"},
{"+H:mm", 12, 30, 0, "+12:30"},
{"+H:mm", 12, 0, 45, "+12"},
{"+H:mm", 12, 30, 45, "+12:30"},
{"+HMM", 2, 0, 0, "+200"},
{"+HMM", -2, 0, 0, "-200"},
{"+HMM", 2, 30, 0, "+230"},
{"+HMM", 2, 0, 45, "+200"},
{"+HMM", 2, 30, 45, "+230"},
{"+HMM", 12, 0, 0, "+1200"},
{"+HMM", -12, 0, 0, "-1200"},
{"+HMM", 12, 30, 0, "+1230"},
{"+HMM", 12, 0, 45, "+1200"},
{"+HMM", 12, 30, 45, "+1230"},
{"+H:MM", 2, 0, 0, "+2:00"},
{"+H:MM", -2, 0, 0, "-2:00"},
{"+H:MM", 2, 30, 0, "+2:30"},
{"+H:MM", 2, 0, 45, "+2:00"},
{"+H:MM", 2, 30, 45, "+2:30"},
{"+H:MM", 12, 0, 0, "+12:00"},
{"+H:MM", -12, 0, 0, "-12:00"},
{"+H:MM", 12, 30, 0, "+12:30"},
{"+H:MM", 12, 0, 45, "+12:00"},
{"+H:MM", 12, 30, 45, "+12:30"},
{"+HMMss", 2, 0, 0, "+200"},
{"+HMMss", -2, 0, 0, "-200"},
{"+HMMss", 2, 30, 0, "+230"},
{"+HMMss", 2, 0, 45, "+20045"},
{"+HMMss", 2, 30, 45, "+23045"},
{"+HMMss", 12, 0, 0, "+1200"},
{"+HMMss", -12, 0, 0, "-1200"},
{"+HMMss", 12, 30, 0, "+1230"},
{"+HMMss", 12, 0, 45, "+120045"},
{"+HMMss", 12, 30, 45, "+123045"},
{"+H:MM:ss", 2, 0, 0, "+2:00"},
{"+H:MM:ss", -2, 0, 0, "-2:00"},
{"+H:MM:ss", 2, 30, 0, "+2:30"},
{"+H:MM:ss", 2, 0, 45, "+2:00:45"},
{"+H:MM:ss", 2, 30, 45, "+2:30:45"},
{"+H:MM:ss", 12, 0, 0, "+12:00"},
{"+H:MM:ss", -12, 0, 0, "-12:00"},
{"+H:MM:ss", 12, 30, 0, "+12:30"},
{"+H:MM:ss", 12, 0, 45, "+12:00:45"},
{"+H:MM:ss", 12, 30, 45, "+12:30:45"},
{"+HMMSS", 2, 0, 0, "+20000"},
{"+HMMSS", -2, 0, 0, "-20000"},
{"+HMMSS", 2, 30, 0, "+23000"},
{"+HMMSS", 2, 0, 45, "+20045"},
{"+HMMSS", 2, 30, 45, "+23045"},
{"+HMMSS", 12, 0, 0, "+120000"},
{"+HMMSS", -12, 0, 0, "-120000"},
{"+HMMSS", 12, 30, 0, "+123000"},
{"+HMMSS", 12, 0, 45, "+120045"},
{"+HMMSS", 12, 30, 45, "+123045"},
{"+H:MM:SS", 2, 0, 0, "+2:00:00"},
{"+H:MM:SS", -2, 0, 0, "-2:00:00"},
{"+H:MM:SS", 2, 30, 0, "+2:30:00"},
{"+H:MM:SS", 2, 0, 45, "+2:00:45"},
{"+H:MM:SS", 2, 30, 45, "+2:30:45"},
{"+H:MM:SS", 12, 0, 0, "+12:00:00"},
{"+H:MM:SS", -12, 0, 0, "-12:00:00"},
{"+H:MM:SS", 12, 30, 0, "+12:30:00"},
{"+H:MM:SS", 12, 0, 45, "+12:00:45"},
{"+H:MM:SS", 12, 30, 45, "+12:30:45"},
{"+Hmmss", 2, 0, 0, "+2"},
{"+Hmmss", -2, 0, 0, "-2"},
{"+Hmmss", 2, 30, 0, "+230"},
{"+Hmmss", 2, 0, 45, "+20045"},
{"+Hmmss", 2, 30, 45, "+23045"},
{"+Hmmss", 12, 0, 0, "+12"},
{"+Hmmss", -12, 0, 0, "-12"},
{"+Hmmss", 12, 30, 0, "+1230"},
{"+Hmmss", 12, 0, 45, "+120045"},
{"+Hmmss", 12, 30, 45, "+123045"},
{"+H:mm:ss", 2, 0, 0, "+2"},
{"+H:mm:ss", -2, 0, 0, "-2"},
{"+H:mm:ss", 2, 30, 0, "+2:30"},
{"+H:mm:ss", 2, 0, 45, "+2:00:45"},
{"+H:mm:ss", 2, 30, 45, "+2:30:45"},
{"+H:mm:ss", 12, 0, 0, "+12"},
{"+H:mm:ss", -12, 0, 0, "-12"},
{"+H:mm:ss", 12, 30, 0, "+12:30"},
{"+H:mm:ss", 12, 0, 45, "+12:00:45"},
{"+H:mm:ss", 12, 30, 45, "+12:30:45"},
};
}
@ -437,8 +558,6 @@ public class TCKDateTimeFormatterBuilder {
{"HH:MM:ss"},
{"HHMMSS"},
{"HH:MM:SS"},
{"+H"},
{"+HMM"},
{"+HHM"},
{"+A"},
};
@ -1188,6 +1307,146 @@ public class TCKDateTimeFormatterBuilder {
{"+HH:mm:ss", "+01", 3600},
{"+HH:mm:ss", "+01:01", 3660},
{"+HH:mm:ss", "+01:01:01", 3661},
{"+H", "+1", 3600},
{"+H", "+101", 3660},
{"+H", "+10101", 3661},
{"+H", "+1:01", 3660},
{"+H", "+1:01:01", 3661},
{"+H", "+01", 3600},
{"+H", "+0101", 3660},
{"+H", "+010101", 3661},
{"+H", "+01:01", 3660},
{"+H", "+01:01:01", 3661},
{"+Hmm", "+1", 3600},
{"+Hmm", "+101", 3660},
{"+Hmm", "+10101", 3661},
{"+Hmm", "+01", 3600},
{"+Hmm", "+0101", 3660},
{"+Hmm", "+010101", 3661},
{"+H:mm", "+1", 3600},
{"+H:mm", "+1:01", 3660},
{"+H:mm", "+1:01:01", 3661},
{"+H:mm", "+01", 3600},
{"+H:mm", "+01:01", 3660},
{"+H:mm", "+01:01:01", 3661},
{"+HMM", "+1", 3600},
{"+HMM", "+101", 3660},
{"+HMM", "+10101", 3661},
{"+HMM", "+01", 3600},
{"+HMM", "+0101", 3660},
{"+HMM", "+010101", 3661},
{"+H:MM", "+1", 3600},
{"+H:MM", "+1:01", 3660},
{"+H:MM", "+1:01:01", 3661},
{"+H:MM", "+01", 3600},
{"+H:MM", "+01:01", 3660},
{"+H:MM", "+01:01:01", 3661},
{"+HMMss", "+1", 3600},
{"+HMMss", "+101", 3660},
{"+HMMss", "+10101", 3661},
{"+HMMss", "+01", 3600},
{"+HMMss", "+0101", 3660},
{"+HMMss", "+010101", 3661},
{"+H:MM:ss", "+1", 3600},
{"+H:MM:ss", "+1:01", 3660},
{"+H:MM:ss", "+1:01:01", 3661},
{"+H:MM:ss", "+01", 3600},
{"+H:MM:ss", "+01:01", 3660},
{"+H:MM:ss", "+01:01:01", 3661},
{"+HMMSS", "+1", 3600},
{"+HMMSS", "+101", 3660},
{"+HMMSS", "+10101", 3661},
{"+HMMSS", "+01", 3600},
{"+HMMSS", "+0101", 3660},
{"+HMMSS", "+010101", 3661},
{"+H:MM:SS", "+1", 3600},
{"+H:MM:SS", "+1:01", 3660},
{"+H:MM:SS", "+1:01:01", 3661},
{"+H:MM:SS", "+01", 3600},
{"+H:MM:SS", "+01:01", 3660},
{"+H:MM:SS", "+01:01:01", 3661},
{"+Hmmss", "+1", 3600},
{"+Hmmss", "+101", 3660},
{"+Hmmss", "+10101", 3661},
{"+Hmmss", "+01", 3600},
{"+Hmmss", "+0101", 3660},
{"+Hmmss", "+010101", 3661},
{"+H:mm:ss", "+1", 3600},
{"+H:mm:ss", "+1:01", 3660},
{"+H:mm:ss", "+1:01:01", 3661},
{"+H:mm:ss", "+01", 3600},
{"+H:mm:ss", "+01:01", 3660},
{"+H:mm:ss", "+01:01:01", 3661},
};
}
@DataProvider(name="strictDoubleDigitHourOffsetParseData")
Object[][] data_strictDoubleDigitHour_offset_parse() {
return new Object[][] {
{"+HH", "+01", 3600},
{"+HHmm", "+01", 3600},
{"+HHmm", "+0101", 3660},
{"+HH:mm", "+01", 3600},
{"+HH:mm", "+01:01", 3660},
{"+HHMM", "+0101", 3660},
{"+HH:MM", "+01:01", 3660},
{"+HHMMss", "+0101", 3660},
{"+HHMMss", "+010101", 3661},
{"+HH:MM:ss", "+01:01", 3660},
{"+HH:MM:ss", "+01:01:01", 3661},
{"+HHMMSS", "+010101", 3661},
{"+HH:MM:SS", "+01:01:01", 3661},
{"+HHmmss", "+01", 3600},
{"+HHmmss", "+0101", 3660},
{"+HHmmss", "+010101", 3661},
{"+HH:mm:ss", "+01", 3600},
{"+HH:mm:ss", "+01:01", 3660},
{"+HH:mm:ss", "+01:01:01", 3661},
};
}
@DataProvider(name="strictSingleDigitHourOffsetParseData")
Object[][] data_strictSingleDigitHour_offset_parse() {
return new Object[][] {
{"+H", "+01", 3600},
{"+H", "+1", 3600},
{"+Hmm", "+01", 3600},
{"+Hmm", "+0101", 3660},
{"+Hmm", "+1", 3600},
{"+Hmm", "+101", 3660},
{"+H:mm", "+01", 3600},
{"+H:mm", "+01:01", 3660},
{"+H:mm", "+1", 3600},
{"+H:mm", "+1:01", 3660},
{"+HMM", "+0101", 3660},
{"+HMM", "+101", 3660},
{"+H:MM", "+01:01", 3660},
{"+H:MM", "+1:01", 3660},
{"+HMMss", "+0101", 3660},
{"+HMMss", "+010101", 3661},
{"+HMMss", "+101", 3660},
{"+HMMss", "+10101", 3661},
{"+H:MM:ss", "+01:01", 3660},
{"+H:MM:ss", "+01:01:01", 3661},
{"+H:MM:ss", "+1:01", 3660},
{"+H:MM:ss", "+1:01:01", 3661},
{"+HMMSS", "+010101", 3661},
{"+HMMSS", "+10101", 3661},
{"+H:MM:SS", "+01:01:01", 3661},
{"+H:MM:SS", "+1:01:01", 3661},
{"+Hmmss", "+01", 3600},
{"+Hmmss", "+0101", 3660},
{"+Hmmss", "+010101", 3661},
{"+Hmmss", "+1", 3600},
{"+Hmmss", "+101", 3660},
{"+Hmmss", "+10101", 3661},
{"+H:mm:ss", "+01", 3600},
{"+H:mm:ss", "+01:01", 3660},
{"+H:mm:ss", "+01:01:01", 3661},
{"+H:mm:ss", "+1", 3600},
{"+H:mm:ss", "+1:01", 3660},
{"+H:mm:ss", "+1:01:01", 3661},
};
}
@ -1203,22 +1462,226 @@ public class TCKDateTimeFormatterBuilder {
3600);
}
@Test(dataProvider="strictDoubleDigitHourOffsetParseData")
public void test_strictDoubleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) {
assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter()
.parse(offset).get(OFFSET_SECONDS), offsetSeconds);
}
@Test(dataProvider="strictDoubleDigitHourOffsetParseData")
public void test_strictDoubleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) {
assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
.appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds);
}
@Test(dataProvider="strictSingleDigitHourOffsetParseData")
public void test_strictSingleDigitHour_offset_parse_1(String pattern, String offset, int offsetSeconds) {
assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter()
.parse(offset).get(OFFSET_SECONDS), offsetSeconds);
}
@Test(dataProvider="strictSingleDigitHourOffsetParseData")
public void test_strictSingleDigitHour_offset_parse_2(String pattern, String offset, int offsetSeconds) {
assertEquals(new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
.appendLiteral("text").toFormatter().parse(offset + "text").get(OFFSET_SECONDS), offsetSeconds);
}
@DataProvider(name="strictOffsetAdjacentParseValidPatternData")
Object[][] data_strict_offset_adjacentParse_validPattern() {
return new Object[][] {
{"+HH", "+01", 3600},
{"+HHmm", "+0101", 3660},
{"+HH:mm", "+01", 3600},
{"+HH:mm", "+01:01", 3660},
{"+HHMM", "+0101", 3660},
{"+HH:MM", "+01:01", 3660},
{"+HHMMss", "+010101", 3661},
{"+HH:MM:ss", "+01:01", 3660},
{"+HH:MM:ss", "+01:01:01", 3661},
{"+HHMMSS", "+010101", 3661},
{"+HH:MM:SS", "+01:01:01", 3661},
{"+HHmmss", "+010101", 3661},
{"+HH:mm:ss", "+01", 3600},
{"+HH:mm:ss", "+01:01", 3660},
{"+HH:mm:ss", "+01:01:01", 3661},
{"+H", "+01", 3600},
{"+Hmm", "+0101", 3660},
{"+H:mm", "+01", 3600},
{"+H:mm", "+01:01", 3660},
{"+H:mm", "+1:01", 3660},
{"+HMM", "+0101", 3660},
{"+H:MM", "+01:01", 3660},
{"+H:MM", "+1:01", 3660},
{"+HMMss", "+010101", 3661},
{"+H:MM:ss", "+01:01", 3660},
{"+H:MM:ss", "+01:01:01", 3661},
{"+H:MM:ss", "+1:01", 3660},
{"+H:MM:ss", "+1:01:01", 3661},
{"+HMMSS", "+010101", 3661},
{"+H:MM:SS", "+01:01:01", 3661},
{"+H:MM:SS", "+1:01:01", 3661},
{"+Hmmss", "+010101", 3661},
{"+H:mm:ss", "+01", 3600},
{"+H:mm:ss", "+01:01", 3660},
{"+H:mm:ss", "+01:01:01", 3661},
{"+H:mm:ss", "+1:01", 3660},
{"+H:mm:ss", "+1:01:01", 3661},
};
}
@Test(dataProvider="strictOffsetAdjacentParseValidPatternData")
public void test_strict_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) {
TemporalAccessor tmp = new DateTimeFormatterBuilder().appendOffset(pattern, "Z")
.appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds);
assertEquals(tmp.get(HOUR_OF_DAY), 12);
}
@DataProvider(name="strictOffsetAdjacentParseInvalidPatternData")
Object[][] data_strict_offset_adjacentParse_invalidPattern() {
return new Object[][] {
{"+HHmm", "+01", 3600},
{"+HHMMss", "+0101", 3660},
{"+HHmmss", "+01", 3600},
{"+HHmmss", "+0101", 3660},
{"+H", "+1", 3600},
{"+Hmm", "+01", 3600},
{"+H:mm", "+1", 3600},
{"+Hmm", "+1", 3600},
{"+Hmm", "+101", 3660},
{"+HMM", "+101", 3660},
{"+HMMss", "+0101", 3660},
{"+HMMss", "+101", 3660},
{"+HMMss", "+10101", 3661},
{"+HMMSS", "+10101", 3661},
{"+Hmmss", "+01", 3600},
{"+Hmmss", "+0101", 3660},
{"+Hmmss", "+1", 3600},
{"+Hmmss", "+101", 3660},
{"+Hmmss", "+10101", 3661},
{"+H:mm:ss", "+1", 3600},
};
}
@Test(dataProvider="strictOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class)
public void test_strict_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) {
new DateTimeFormatterBuilder().appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2)
.toFormatter().parse(offset + "12");
}
@DataProvider(name="lenientOffsetAdjacentParseValidPatternData")
Object[][] data_lenient_offset_adjacentParse_validPattern() {
return new Object[][] {
{"+HH:mm", "+01", 3600},
{"+HH:mm", "+01:01", 3660},
{"+HH:MM", "+01:01", 3660},
{"+HH:MM:ss", "+01:01", 3660},
{"+HH:MM:ss", "+01:01:01", 3661},
{"+HHMMSS", "+010101", 3661},
{"+HH:MM:SS", "+01:01:01", 3661},
{"+HHmmss", "+010101", 3661},
{"+HH:mm:ss", "+01", 3600},
{"+HH:mm:ss", "+01:01", 3660},
{"+HH:mm:ss", "+01:01:01", 3661},
{"+H:mm", "+01", 3600},
{"+H:mm", "+01:01", 3660},
{"+H:mm", "+1:01", 3660},
{"+H:MM", "+01:01", 3660},
{"+H:MM", "+1:01", 3660},
{"+HMMss", "+010101", 3661},
{"+H:MM:ss", "+01:01", 3660},
{"+H:MM:ss", "+01:01:01", 3661},
{"+H:MM:ss", "+1:01", 3660},
{"+H:MM:ss", "+1:01:01", 3661},
{"+HMMSS", "+010101", 3661},
{"+H:MM:SS", "+01:01:01", 3661},
{"+H:MM:SS", "+1:01:01", 3661},
{"+Hmmss", "+010101", 3661},
{"+H:mm:ss", "+01", 3600},
{"+H:mm:ss", "+01:01", 3660},
{"+H:mm:ss", "+01:01:01", 3661},
{"+H:mm:ss", "+1:01", 3660},
{"+H:mm:ss", "+1:01:01", 3661},
};
}
@Test(dataProvider="lenientOffsetAdjacentParseValidPatternData")
public void test_lenient_offset_adjacentValidPattern_parse(String pattern, String offset, int offsetSeconds) {
TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient()
.appendOffset(pattern, "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
assertEquals(tmp.get(OFFSET_SECONDS), offsetSeconds);
assertEquals(tmp.get(HOUR_OF_DAY), 12);
}
@Test
public void test_lenient_offset_adjacentValidPattern_parse1() {
TemporalAccessor tmp = new DateTimeFormatterBuilder().parseLenient()
.appendOffset("+HMMSS", "Z").appendValue(HOUR_OF_DAY, 2).toFormatter().parse("+10101" + "12");
//Equivalent to +101011. In lenient mode, offset will parse upto 6 digit if possible.
//It will take 1 digit from HOUR_OF_DAY.
assertEquals(tmp.get(OFFSET_SECONDS), 36611);
assertEquals(tmp.get(HOUR_OF_DAY), 2);
}
@DataProvider(name="lenientOffsetAdjacentParseInvalidPatternData")
Object[][] data_lenient_offset_adjacentParse_invalidPattern() {
return new Object[][] {
{"+HH", "+01", 3600},
{"+HHmm", "+0101", 3660},
{"+HHMM", "+0101", 3660},
{"+H", "+01", 3600},
{"+Hmm", "+0101", 3660},
{"+HMM", "+0101", 3660},
};
}
@Test(dataProvider="lenientOffsetAdjacentParseInvalidPatternData", expectedExceptions=DateTimeParseException.class)
public void test_lenient_offset_adjacentInvalidPattern_parse(String pattern, String offset, int offsetSeconds) {
new DateTimeFormatterBuilder().parseLenient().appendOffset(pattern, "Z")
.appendValue(HOUR_OF_DAY, 2).toFormatter().parse(offset + "12");
}
@DataProvider(name="badValues")
Object[][] data_badOffsetValues() {
return new Object[][] {
{"+HH", "+24"},
{"+HHMM", "-1361"},
{"+HH:MM:ss", "+13:12:66"},
{"+HH:MM:SS", "+24:60:60"},
{"+HHMMSS", "369999"},
{"+H:MM", "+28:12"},
};
}
@Test(dataProvider="badValues", expectedExceptions=DateTimeParseException.class)
public void test_badOffset_parse(String pattern, String offset) {
new DateTimeFormatterBuilder().appendOffset(pattern, "Z").toFormatter().parse(offset);
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffsetId() {
assertEquals(new DateTimeFormatterBuilder().appendOffsetId().toFormatter().parse("+01").get(OFFSET_SECONDS),
3600);
new DateTimeFormatterBuilder().appendOffsetId().toFormatter().parse("+01");
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffset_1() {
assertEquals(new DateTimeFormatterBuilder().appendOffset("+HH:MM:ss", "Z").toFormatter().parse("+01").get(OFFSET_SECONDS),
3600);
new DateTimeFormatterBuilder().appendOffset("+HH:MM:ss", "Z").toFormatter().parse("+01");
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffset_2() {
assertEquals(new DateTimeFormatterBuilder().appendOffset("+HHMMss", "Z").toFormatter().parse("+01").get(OFFSET_SECONDS),
3600);
new DateTimeFormatterBuilder().appendOffset("+HHMMss", "Z").toFormatter().parse("+01");
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffset_3() {
new DateTimeFormatterBuilder().appendOffset("+H:MM:ss", "Z").toFormatter().parse("+1");
}
@Test(expectedExceptions=DateTimeParseException.class)
public void test_strict_appendOffset_4() {
new DateTimeFormatterBuilder().appendOffset("+HMMss", "Z").toFormatter().parse("+1");
}
@Test

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -93,6 +93,14 @@ public class TCKOffsetPrinterParser {
private static final ZoneOffset OFFSET_M000045 = ZoneOffset.ofHoursMinutesSeconds(0, 0, -45);
private static final LocalDateTime DT_2012_06_30_12_30_40 = LocalDateTime.of(2012, 6, 30, 12, 30, 40);
private static final ZoneOffset OFFSET_P1100 = ZoneOffset.ofHours(11);
private static final ZoneOffset OFFSET_P1123 = ZoneOffset.ofHoursMinutes(11, 23);
private static final ZoneOffset OFFSET_P1023 = ZoneOffset.ofHoursMinutes(10, 23);
private static final ZoneOffset OFFSET_P112345 = ZoneOffset.ofHoursMinutesSeconds(11, 23, 45);
private static final ZoneOffset OFFSET_P100045 = ZoneOffset.ofHoursMinutesSeconds(10, 0, 45);
private static final ZoneOffset OFFSET_M1100 = ZoneOffset.ofHours(-11);
private static final ZoneOffset OFFSET_M1123 = ZoneOffset.ofHoursMinutes(-11, -23);
private static final ZoneOffset OFFSET_M112345 = ZoneOffset.ofHoursMinutesSeconds(-11, -23, -45);
private DateTimeFormatterBuilder builder;
@BeforeMethod
@ -223,6 +231,212 @@ public class TCKOffsetPrinterParser {
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0023"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-012345"},
{"+HHmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-000045"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "Z"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "Z"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+123"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-123"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+100"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-100"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "Z"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "Z"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+100"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+00045"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-100"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+10000"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+12300"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+02300"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-10000"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-12300"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-02300"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1:00:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1:00:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+1:23"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+0:23"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+1:23:45"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-1:23"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-0:23"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-1:23:45"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-0:00:45"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_UTC, "Z"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0100, "+1"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0123, "+123"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P0023, "+023"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P012345, "+12345"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P000045, "+00045"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0100, "-1"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0123, "-123"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M0023, "-023"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M012345, "-12345"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M000045, "-00045"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11"},
{"+H", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+1123"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
{"+Hmm", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-1123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+1100"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+1123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+1000"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-1100"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
{"+HMM", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-1123"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+10:00"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
{"+H:MM", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+1100"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+100045"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-1100"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
{"+HMMss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
{"+H:MM:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+110000"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+112300"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+102300"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-110000"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-112300"},
{"+HMMSS", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11:00:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11:00:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23:00"},
{"+H:MM:SS", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+11:23"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+10:23"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+11:23:45"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-11:23"},
{"+H:mm:ss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-11:23:45"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1100, "+11"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1123, "+1123"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P1023, "+1023"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P112345, "+112345"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_P100045, "+100045"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1100, "-11"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M1123, "-1123"},
{"+Hmmss", "Z", DT_2012_06_30_12_30_40, OFFSET_M112345, "-112345"},
};
}

View File

@ -484,8 +484,6 @@ public class TestDateTimeFormatterBuilder {
{"HH:MM:ss"},
{"HHMMSS"},
{"HH:MM:SS"},
{"+H"},
{"+HMM"},
{"+HHM"},
{"+A"},
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -296,7 +296,7 @@ public class TestZoneOffsetParser extends AbstractTestPrinterParser {
@DataProvider(name="bigOffsets")
Object[][] provider_bigOffsets() {
return new Object[][] {
{"+HH", "+59", 59 * 3600},
{"+HH", "+19", 19 * 3600},
{"+HH", "-19", -(19 * 3600)},
{"+HHMM", "+1801", 18 * 3600 + 1 * 60},