--- old/src/share/classes/java/util/Formatter.java 2013-01-22 16:57:34.000000000 -0800 +++ new/src/share/classes/java/util/Formatter.java 2013-01-22 16:57:34.000000000 -0800 @@ -50,6 +50,21 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.time.Clock; +import java.time.DateTimeException; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.Queries; +import java.time.temporal.OffsetDate; +import java.time.temporal.OffsetDateTime; +import java.time.temporal.OffsetTime; +import java.time.temporal.ChronoZonedDateTime; +import java.time.format.TextStyle; +import java.time.zone.ZoneRules; + import sun.misc.DoubleConsts; import sun.misc.FormattedFloatingDecimal; @@ -254,8 +269,8 @@ * * *
  • Date/Time - may be applied to Java types which are capable of - * encoding a date or time: {@code long}, {@link Long}, {@link Calendar}, and - * {@link Date}. + * encoding a date or time: {@code long}, {@link Long}, {@link Calendar}, + * {@link Date} and {@link TemporalAccessor TemporalAccessor} * *
  • Percent - produces a literal {@code '%'} * ('\u0025') @@ -1488,7 +1503,7 @@ *

    Date/Time

    * *

    This conversion may be applied to {@code long}, {@link Long}, {@link - * Calendar}, and {@link Date}. + * Calendar}, {@link Date} and {@link TemporalAccessor TemporalAccessor} * * * @@ -2782,6 +2797,9 @@ } else if (arg instanceof Calendar) { cal = (Calendar) ((Calendar)arg).clone(); cal.setLenient(true); + } else if (arg instanceof TemporalAccessor) { + print((TemporalAccessor)arg, c, l); + return; } else { failConversion(c, arg); } @@ -4032,6 +4050,242 @@ return sb; } + private void print(TemporalAccessor t, char c, Locale l) throws IOException { + StringBuilder sb = new StringBuilder(); + print(sb, t, c, l); + // justify based on width + String s = justify(sb.toString()); + if (f.contains(Flags.UPPERCASE)) + s = s.toUpperCase(); + a.append(s); + } + + private Appendable print(StringBuilder sb, TemporalAccessor t, char c, + Locale l) throws IOException { + if (sb == null) + sb = new StringBuilder(); + try { + switch (c) { + case DateTime.HOUR_OF_DAY_0: { // 'H' (00 - 23) + int i = t.get(ChronoField.HOUR_OF_DAY); + sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l)); + break; + } + case DateTime.HOUR_OF_DAY: { // 'k' (0 - 23) -- like H + int i = t.get(ChronoField.HOUR_OF_DAY); + sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l)); + break; + } + case DateTime.HOUR_0: { // 'I' (01 - 12) + int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM); + sb.append(localizedMagnitude(null, i, Flags.ZERO_PAD, 2, l)); + break; + } + case DateTime.HOUR: { // 'l' (1 - 12) -- like I + int i = t.get(ChronoField.CLOCK_HOUR_OF_AMPM); + sb.append(localizedMagnitude(null, i, Flags.NONE, 2, l)); + break; + } + case DateTime.MINUTE: { // 'M' (00 - 59) + int i = t.get(ChronoField.MINUTE_OF_HOUR); + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, i, flags, 2, l)); + break; + } + case DateTime.NANOSECOND: { // 'N' (000000000 - 999999999) + int i = t.get(ChronoField.MILLI_OF_SECOND) * 1000000; + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, i, flags, 9, l)); + break; + } + case DateTime.MILLISECOND: { // 'L' (000 - 999) + int i = t.get(ChronoField.MILLI_OF_SECOND); + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, i, flags, 3, l)); + break; + } + case DateTime.MILLISECOND_SINCE_EPOCH: { // 'Q' (0 - 99...?) + long i = t.getLong(ChronoField.INSTANT_SECONDS) * 1000L + + t.getLong(ChronoField.MILLI_OF_SECOND); + Flags flags = Flags.NONE; + sb.append(localizedMagnitude(null, i, flags, width, l)); + break; + } + case DateTime.AM_PM: { // 'p' (am or pm) + // Calendar.AM = 0, Calendar.PM = 1, LocaleElements defines upper + String[] ampm = { "AM", "PM" }; + if (l != null && l != Locale.US) { + DateFormatSymbols dfs = DateFormatSymbols.getInstance(l); + ampm = dfs.getAmPmStrings(); + } + String s = ampm[t.get(ChronoField.AMPM_OF_DAY)]; + sb.append(s.toLowerCase(l != null ? l : Locale.US)); + break; + } + case DateTime.SECONDS_SINCE_EPOCH: { // 's' (0 - 99...?) + long i = t.getLong(ChronoField.INSTANT_SECONDS); + Flags flags = Flags.NONE; + sb.append(localizedMagnitude(null, i, flags, width, l)); + break; + } + case DateTime.SECOND: { // 'S' (00 - 60 - leap second) + int i = t.get(ChronoField.SECOND_OF_MINUTE); + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, i, flags, 2, l)); + break; + } + case DateTime.ZONE_NUMERIC: { // 'z' ({-|+}####) - ls minus? + int i = t.get(ChronoField.OFFSET_SECONDS); + boolean neg = i < 0; + sb.append(neg ? '-' : '+'); + if (neg) + i = -i; + int min = i / 60; + // combine minute and hour into a single integer + int offset = (min / 60) * 100 + (min % 60); + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, offset, flags, 4, l)); + break; + } + case DateTime.ZONE: { // 'Z' (symbol) + ZoneId zid = t.query(Queries.zone()); + if (zid == null) { + throw new IllegalFormatConversionException(c, t.getClass()); + } + if (!(zid instanceof ZoneOffset) && + t.isSupported(ChronoField.INSTANT_SECONDS)) { + Instant instant = Instant.from(t); + sb.append(TimeZone.getTimeZone(zid.getId()) + .getDisplayName(zid.getRules().isDaylightSavings(instant), + TimeZone.SHORT, + (l == null) ? Locale.US : l)); + break; + } + sb.append(zid.getId()); + break; + } + // Date + case DateTime.NAME_OF_DAY_ABBREV: // 'a' + case DateTime.NAME_OF_DAY: { // 'A' + int i = t.get(ChronoField.DAY_OF_WEEK) % 7 + 1; + Locale lt = ((l == null) ? Locale.US : l); + DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); + if (c == DateTime.NAME_OF_DAY) + sb.append(dfs.getWeekdays()[i]); + else + sb.append(dfs.getShortWeekdays()[i]); + break; + } + case DateTime.NAME_OF_MONTH_ABBREV: // 'b' + case DateTime.NAME_OF_MONTH_ABBREV_X: // 'h' -- same b + case DateTime.NAME_OF_MONTH: { // 'B' + int i = t.get(ChronoField.MONTH_OF_YEAR) - 1; + Locale lt = ((l == null) ? Locale.US : l); + DateFormatSymbols dfs = DateFormatSymbols.getInstance(lt); + if (c == DateTime.NAME_OF_MONTH) + sb.append(dfs.getMonths()[i]); + else + sb.append(dfs.getShortMonths()[i]); + break; + } + case DateTime.CENTURY: // 'C' (00 - 99) + case DateTime.YEAR_2: // 'y' (00 - 99) + case DateTime.YEAR_4: { // 'Y' (0000 - 9999) + int i = t.get(ChronoField.YEAR); + int size = 2; + switch (c) { + case DateTime.CENTURY: + i /= 100; + break; + case DateTime.YEAR_2: + i %= 100; + break; + case DateTime.YEAR_4: + size = 4; + break; + } + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, i, flags, size, l)); + break; + } + case DateTime.DAY_OF_MONTH_0: // 'd' (01 - 31) + case DateTime.DAY_OF_MONTH: { // 'e' (1 - 31) -- like d + int i = t.get(ChronoField.DAY_OF_MONTH); + Flags flags = (c == DateTime.DAY_OF_MONTH_0 + ? Flags.ZERO_PAD + : Flags.NONE); + sb.append(localizedMagnitude(null, i, flags, 2, l)); + break; + } + case DateTime.DAY_OF_YEAR: { // 'j' (001 - 366) + int i = t.get(ChronoField.DAY_OF_YEAR); + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, i, flags, 3, l)); + break; + } + case DateTime.MONTH: { // 'm' (01 - 12) + int i = t.get(ChronoField.MONTH_OF_YEAR); + Flags flags = Flags.ZERO_PAD; + sb.append(localizedMagnitude(null, i, flags, 2, l)); + break; + } + + // Composites + case DateTime.TIME: // 'T' (24 hour hh:mm:ss - %tH:%tM:%tS) + case DateTime.TIME_24_HOUR: { // 'R' (hh:mm same as %H:%M) + char sep = ':'; + print(sb, t, DateTime.HOUR_OF_DAY_0, l).append(sep); + print(sb, t, DateTime.MINUTE, l); + if (c == DateTime.TIME) { + sb.append(sep); + print(sb, t, DateTime.SECOND, l); + } + break; + } + case DateTime.TIME_12_HOUR: { // 'r' (hh:mm:ss [AP]M) + char sep = ':'; + print(sb, t, DateTime.HOUR_0, l).append(sep); + print(sb, t, DateTime.MINUTE, l).append(sep); + print(sb, t, DateTime.SECOND, l).append(' '); + // this may be in wrong place for some locales + StringBuilder tsb = new StringBuilder(); + print(tsb, t, DateTime.AM_PM, l); + sb.append(tsb.toString().toUpperCase(l != null ? l : Locale.US)); + break; + } + case DateTime.DATE_TIME: { // 'c' (Sat Nov 04 12:02:33 EST 1999) + char sep = ' '; + print(sb, t, DateTime.NAME_OF_DAY_ABBREV, l).append(sep); + print(sb, t, DateTime.NAME_OF_MONTH_ABBREV, l).append(sep); + print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); + print(sb, t, DateTime.TIME, l).append(sep); + print(sb, t, DateTime.ZONE, l).append(sep); + print(sb, t, DateTime.YEAR_4, l); + break; + } + case DateTime.DATE: { // 'D' (mm/dd/yy) + char sep = '/'; + print(sb, t, DateTime.MONTH, l).append(sep); + print(sb, t, DateTime.DAY_OF_MONTH_0, l).append(sep); + print(sb, t, DateTime.YEAR_2, l); + break; + } + case DateTime.ISO_STANDARD_DATE: { // 'F' (%Y-%m-%d) + char sep = '-'; + print(sb, t, DateTime.YEAR_4, l).append(sep); + print(sb, t, DateTime.MONTH, l).append(sep); + print(sb, t, DateTime.DAY_OF_MONTH_0, l); + break; + } + default: + assert false; + } + } catch (DateTimeException x) { + throw new IllegalFormatConversionException(c, t.getClass()); + } + return sb; + } + // -- Methods to support throwing exceptions -- private void failMismatch(Flags f, char c) {