diff --git a/src/changes/changes.xml b/src/changes/changes.xml index d5a33dd2b..c6032259d 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + FastDateParser does not handle excess hours as per SimpleDateFormat FastDateParser error - timezones not handled correctly NumberUtils#createNumber() returns positive BigDecimal when negative Float is expected DiffBuilder.append(String, Object left, Object right) does not do a left.equals(right) check diff --git a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java index 4d1a3c0b0..8e3979254 100644 --- a/src/main/java/org/apache/commons/lang3/time/FastDateParser.java +++ b/src/main/java/org/apache/commons/lang3/time/FastDateParser.java @@ -487,7 +487,7 @@ private Strategy getStrategy(final String formatField, final Calendar definingCa case 'G': return getLocaleSpecificStrategy(Calendar.ERA, definingCalendar); case 'H': // Hour in day (0-23) - return MODULO_HOUR_OF_DAY_STRATEGY; + return HOUR_OF_DAY_STRATEGY; case 'K': // Hour in am/pm (0-11) return HOUR_STRATEGY; case 'M': @@ -501,9 +501,9 @@ private Strategy getStrategy(final String formatField, final Calendar definingCa case 'd': return DAY_OF_MONTH_STRATEGY; case 'h': // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 - return MODULO_HOUR_STRATEGY; + return HOUR12_STRATEGY; case 'k': // Hour in day (1-24), i.e. midnight is 24, not 0 - return HOUR_OF_DAY_STRATEGY; + return HOUR24_OF_DAY_STRATEGY; case 'm': return MINUTE_STRATEGY; case 's': @@ -859,16 +859,16 @@ int modify(final int iValue) { private static final Strategy DAY_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_MONTH); private static final Strategy DAY_OF_WEEK_IN_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK_IN_MONTH); private static final Strategy HOUR_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY); - private static final Strategy MODULO_HOUR_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY) { + private static final Strategy HOUR24_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY) { @Override int modify(final int iValue) { - return iValue%24; + return iValue == 24 ? 0 : iValue; } }; - private static final Strategy MODULO_HOUR_STRATEGY = new NumberStrategy(Calendar.HOUR) { + private static final Strategy HOUR12_STRATEGY = new NumberStrategy(Calendar.HOUR) { @Override int modify(final int iValue) { - return iValue%12; + return iValue == 12 ? 0 : iValue; } }; private static final Strategy HOUR_STRATEGY = new NumberStrategy(Calendar.HOUR); diff --git a/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java b/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java index 5c9363fec..816f38e92 100644 --- a/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java +++ b/src/test/java/org/apache/commons/lang3/time/FastDateParserSDFTest.java @@ -38,6 +38,52 @@ public static Collection data() { // year tests { "MM/dd/yyyy", "01/11/12", Locale.UK, true}, { "MM/dd/yy", "01/11/12", Locale.UK, true}, + + // LANG-1089 + { "HH", "00", Locale.UK, true}, // Hour in day (0-23) + { "KK", "00", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "00", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "00", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "01", Locale.UK, true}, // Hour in day (0-23) + { "KK", "01", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "01", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "01", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "11", Locale.UK, true}, // Hour in day (0-23) + { "KK", "11", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "11", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "11", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "12", Locale.UK, true}, // Hour in day (0-23) + { "KK", "12", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "12", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "12", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "13", Locale.UK, true}, // Hour in day (0-23) + { "KK", "13", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "13", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "13", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "23", Locale.UK, true}, // Hour in day (0-23) + { "KK", "23", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "23", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "23", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "24", Locale.UK, true}, // Hour in day (0-23) + { "KK", "24", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "24", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "24", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "25", Locale.UK, true}, // Hour in day (0-23) + { "KK", "25", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "25", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "25", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 + + { "HH", "48", Locale.UK, true}, // Hour in day (0-23) + { "KK", "48", Locale.UK, true}, // Hour in am/pm (0-11) + { "hh", "48", Locale.UK, true}, // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 + { "kk", "48", Locale.UK, true}, // Hour in day (1-24), i.e. midnight is 24, not 0 }); }