--- old/modules/controls/src/main/java/javafx/scene/control/DatePicker.java 2014-08-04 16:58:36.775035679 -0700
+++ new/modules/controls/src/main/java/javafx/scene/control/DatePicker.java 2014-08-04 16:58:36.623035678 -0700
@@ -32,11 +32,7 @@
import java.time.chrono.Chronology;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.IsoChronology;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeFormatterBuilder;
-import java.time.format.DecimalStyle;
import java.time.format.FormatStyle;
-import java.time.temporal.TemporalAccessor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -58,6 +54,7 @@
import javafx.scene.AccessibleRole;
import javafx.util.Callback;
import javafx.util.StringConverter;
+import javafx.util.converter.LocalDateStringConverter;
import com.sun.javafx.css.converters.BooleanConverter;
import com.sun.javafx.scene.control.skin.DatePickerSkin;
@@ -136,6 +133,7 @@
if (validateDate(chrono, date)) {
lastValidChronology = chrono;
+ defaultConverter = new LocalDateStringConverter(FormatStyle.SHORT, null, chrono);
} else {
System.err.println("Restoring value to " + lastValidChronology);
setChronology(lastValidChronology);
@@ -304,7 +302,7 @@
* versa.
*
*
If not set by the application, the DatePicker skin class will
- * set a converter based on a {@link java.time.DateTimeFormatter}
+ * set a converter based on a {@link java.time.format.DateTimeFormatter}
* for the current {@link java.util.Locale} and
* {@link #chronologyProperty() chronology}. This formatter is
* then used to parse and display the current date value.
@@ -402,64 +400,9 @@
}
}
- private StringConverter defaultConverter = new StringConverter() {
- @Override public String toString(LocalDate value) {
- if (value != null) {
- Locale locale = Locale.getDefault(Locale.Category.FORMAT);
- Chronology chrono = getChronology();
- ChronoLocalDate cDate;
- try {
- cDate = chrono.date(value);
- } catch (DateTimeException ex) {
- System.err.println(ex);
- chrono = IsoChronology.INSTANCE;
- cDate = value;
- }
- DateTimeFormatter dateFormatter =
- DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
- .withLocale(locale)
- .withChronology(chrono)
- .withDecimalStyle(DecimalStyle.of(locale));
-
- String pattern =
- DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT,
- null, chrono, locale);
-
- if (pattern.contains("yy") && !pattern.contains("yyy")) {
- // Modify pattern to show four-digit year, including leading zeros.
- String newPattern = pattern.replace("yy", "yyyy");
- //System.err.println("Fixing pattern ("+forParsing+"): "+pattern+" -> "+newPattern);
- dateFormatter = DateTimeFormatter.ofPattern(newPattern)
- .withDecimalStyle(DecimalStyle.of(locale));
- }
-
- return dateFormatter.format(cDate);
- } else {
- return "";
- }
- }
-
- @Override public LocalDate fromString(String text) {
- if (text != null && !text.isEmpty()) {
- Locale locale = Locale.getDefault(Locale.Category.FORMAT);
- Chronology chrono = getChronology();
-
- String pattern =
- DateTimeFormatterBuilder.getLocalizedDateTimePattern(FormatStyle.SHORT,
- null, chrono, locale);
- DateTimeFormatter df =
- new DateTimeFormatterBuilder().parseLenient()
- .appendPattern(pattern)
- .toFormatter()
- .withChronology(chrono)
- .withDecimalStyle(DecimalStyle.of(locale));
- TemporalAccessor temporal = df.parse(text);
- ChronoLocalDate cDate = chrono.date(temporal);
- return LocalDate.from(cDate);
- }
- return null;
- }
- };
+ // Create a symmetric (format/parse) converter with the default locale.
+ private StringConverter defaultConverter =
+ new LocalDateStringConverter(FormatStyle.SHORT, null, getChronology());
// --- Editor
--- old/modules/controls/src/test/java/javafx/scene/control/DatePickerTest.java 2014-08-04 16:58:37.559035686 -0700
+++ new/modules/controls/src/test/java/javafx/scene/control/DatePickerTest.java 2014-08-04 16:58:37.403035685 -0700
@@ -385,12 +385,10 @@
********************************************************************/
@Test public void test_rt30549() {
- StringConverter converter = datePicker.getConverter();
-
// Set a MinguoDate from a String
datePicker.setChronology(MinguoChronology.INSTANCE);
datePicker.getEditor().setText("5/22/0102 1");
- datePicker.setValue(converter.fromString(datePicker.getEditor().getText()));
+ datePicker.setValue(datePicker.getConverter().fromString(datePicker.getEditor().getText()));
assertEquals(MinguoChronology.INSTANCE.date(MinguoEra.ROC, 102, 5, 22),
MinguoDate.from(datePicker.getValue()));
assertEquals("5/22/0102 1", datePicker.getEditor().getText());
@@ -398,7 +396,7 @@
// Convert from MinguoDate to LocalDate (ISO)
datePicker.setChronology(IsoChronology.INSTANCE);
assertEquals(LocalDate.of(2013, 5, 22), datePicker.getValue());
- datePicker.getEditor().setText(converter.toString(datePicker.getValue()));
+ datePicker.getEditor().setText(datePicker.getConverter().toString(datePicker.getValue()));
assertEquals("5/22/2013", datePicker.getEditor().getText());
}
--- /dev/null 2014-07-27 19:38:16.499796011 -0700
+++ new/modules/base/src/main/java/javafx/util/converter/LocalDateStringConverter.java 2014-08-04 16:58:38.151035691 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.util.converter;
+
+import java.time.LocalDate;
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Locale;
+
+import javafx.util.StringConverter;
+import javafx.util.converter.LocalDateTimeStringConverter.LdtConverter;
+
+/**
+ * {@link StringConverter} implementation for {@link LocalDate} values.
+ *
+ * @see LocalTimeStringConverter
+ * @see LocalDateTimeStringConverter
+ * @since JavaFX 8u40
+ */
+public class LocalDateStringConverter extends StringConverter {
+
+ LdtConverter ldtConverter;
+
+ // ------------------------------------------------------------ Constructors
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalDate} values, using a
+ * default formatter and parser based on {@link IsoChronology},
+ * {@link FormatStyle#SHORT}, and the user's {@link Locale}.
+ *
+ * This converter ensures symmetry between the toString() and
+ * fromString() methods. Many of the default locale based patterns used by
+ * {@link DateTimeFormatter} will display only two digits for the year when
+ * formatting to a string. This would cause a value like 1955 to be
+ * displayed as 55, which in turn would be parsed back as 2055. This
+ * converter modifies two-digit year patterns to always use four digits. The
+ * input parsing is not affected, so two digit year values can still be
+ * parsed leniently as expected in these locales.
+ */
+ public LocalDateStringConverter() {
+ ldtConverter = new LdtConverter(LocalDate.class, null, null,
+ null, null, null, null);
+ }
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalDate} values, using a
+ * default formatter and parser based on {@link IsoChronology},
+ * the specified {@link FormatStyle}, and the user's {@link Locale}.
+ *
+ * @param dateStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser. If null then {@link FormatStyle#SHORT} will be used.
+ */
+ public LocalDateStringConverter(FormatStyle dateStyle) {
+ ldtConverter = new LdtConverter(LocalDate.class, null, null,
+ dateStyle, null, null, null);
+ }
+
+ /**
+ * Create a {#link StringConverter} for {@link LocalDate} values using the supplied
+ * formatter and parser.
+ *
+ * For example, to use a fixed pattern for converting both ways:
+ *
+ * String pattern = "yyyy-MM-dd";
+ * DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+ * StringConverter converter =
+ * DateTimeStringConverter.getLocalDateStringConverter(formatter, null);
+ *
+ *
+ * Note that the formatter and parser can be created to handle non-default
+ * {@link Locale} and {@link Chronology} as needed.
+ *
+ * @param formatter An instance of {@link DateTimeFormatter} that will be
+ * used for formatting by the toString() method. If null then a default
+ * formatter will be used.
+ * @param parser An instance of {@link DateTimeFormatter} that will be used
+ * for parsing by the fromString() method. This can be identical to
+ * formatter. If null then formatter will be used, and if that is also null,
+ * then a default parser will be used.
+ */
+ public LocalDateStringConverter(DateTimeFormatter formatter, DateTimeFormatter parser) {
+ ldtConverter = new LdtConverter(LocalDate.class, formatter, parser,
+ null, null, null, null);
+ }
+
+
+ /**
+ * Create a StringConverter for {@link LocalDate} values using a default
+ * formatter and parser, which will be based on the supplied
+ * {@link FormatStyle}, {@link Locale}, and {@link Chronology}.
+ *
+ * @param dateStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser. If null then {@link FormatStyle#SHORT} will be used.
+ * @param locale The {@link Locale} that will be used by the default
+ * formatter and parser. If null then
+ * {@code Locale.getDefault(Locale.Category.FORMAT)} will be used.
+ * @param chronology The {@link Chronology} that will be used by the default
+ * formatter and parser. If null then {@link IsoChronology#INSTANCE} will be used.
+ */
+ public LocalDateStringConverter(FormatStyle dateStyle, Locale locale, Chronology chronology) {
+ ldtConverter = new LdtConverter(LocalDate.class, null, null,
+ dateStyle, null, locale, chronology);
+ }
+
+ // ------------------------------------------------------- Converter Methods
+
+ /** {@inheritDoc} */
+ @Override public LocalDate fromString(String value) {
+ return ldtConverter.fromString(value);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString(LocalDate value) {
+ return ldtConverter.toString(value);
+ }
+
+}
--- /dev/null 2014-07-27 19:38:16.499796011 -0700
+++ new/modules/base/src/main/java/javafx/util/converter/LocalDateTimeStringConverter.java 2014-08-04 16:58:38.859035697 -0700
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.util.converter;
+
+import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.time.chrono.Chronology;
+import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.ChronoLocalDateTime;
+import java.time.chrono.IsoChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.format.DecimalStyle;
+import java.time.format.FormatStyle;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAccessor;
+import java.util.Locale;
+
+import javafx.util.StringConverter;
+
+/**
+ * {@link StringConverter} implementation for {@link LocalDateTime} values.
+ *
+ * @see LocalDateStringConverter
+ * @see LocalTimeStringConverter
+ * @since JavaFX 8u40
+ */
+public class LocalDateTimeStringConverter extends StringConverter {
+
+ LdtConverter ldtConverter;
+
+
+
+ // ------------------------------------------------------------ Constructors
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalDateTime} values, using a
+ * default formatter and parser based on {@link IsoChronology},
+ * {@link FormatStyle#SHORT} for both date and time, and the user's
+ * {@link Locale}.
+ *
+ * This converter ensures symmetry between the toString() and
+ * fromString() methods. Many of the default locale based patterns used by
+ * {@link DateTimeFormatter} will display only two digits for the year when
+ * formatting to a string. This would cause a value like 1955 to be
+ * displayed as 55, which in turn would be parsed back as 2055. This
+ * converter modifies two-digit year patterns to always use four digits. The
+ * input parsing is not affected, so two digit year values can still be
+ * parsed as expected in these locales.
+ */
+ public LocalDateTimeStringConverter() {
+ ldtConverter = new LdtConverter(LocalDateTime.class, null, null,
+ null, null, null, null);
+ }
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalDateTime} values, using
+ * a default formatter and parser based on {@link IsoChronology}, the
+ * specified {@link FormatStyle} values for date and time, and the user's
+ * {@link Locale}.
+ *
+ * @param dateStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser for the date. If null then {@link FormatStyle#SHORT}
+ * will be used.
+ * @param timeStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser for the time. If null then {@link FormatStyle#SHORT}
+ * will be used.
+ */
+ public LocalDateTimeStringConverter(FormatStyle dateStyle, FormatStyle timeStyle) {
+ ldtConverter = new LdtConverter(LocalDateTime.class, null, null,
+ dateStyle, timeStyle, null, null);
+ }
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalDateTime} values using
+ * the supplied formatter and parser.
+ *
+ * For example, to use a fixed pattern for converting both ways:
+ *
+ * String pattern = "yyyy-MM-dd HH:mm";
+ * DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+ * StringConverter converter =
+ * DateTimeStringConverter.getLocalDateTimeConverter(formatter, null);
+ *
+ *
+ * Note that the formatter and parser can be created to handle non-default
+ * {@link Locale} and {@link Chronology} as needed.
+ *
+ * @param formatter An instance of {@link DateTimeFormatter} which will be
+ * used for formatting by the toString() method. If null then a default
+ * formatter will be used.
+ * @param parser An instance of {@link DateTimeFormatter} which will be used
+ * for parsing by the fromString() method. This can be identical to
+ * formatter. If null then formatter will be used, and if that is also null,
+ * then a default parser will be used.
+ */
+ public LocalDateTimeStringConverter(DateTimeFormatter formatter, DateTimeFormatter parser) {
+ ldtConverter = new LdtConverter(LocalDateTime.class, formatter, parser,
+ null, null, null, null);
+ }
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalDateTime} values using a
+ * default formatter and parser, which will be based on the supplied
+ * {@link FormatStyle}s, {@link Locale}, and {@link Chronology}.
+ *
+ * @param dateStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser for the date. If null then {@link FormatStyle#SHORT}
+ * will be used.
+ * @param timeStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser for the time. If null then {@link FormatStyle#SHORT}
+ * will be used.
+ * @param locale The {@link Locale} that will be used by the
+ * default formatter and parser. If null then
+ * {@code Locale.getDefault(Locale.Category.FORMAT)} will be used.
+ * @param chronology The {@link Chronology} that will be used by the default
+ * formatter and parser. If null then {@link IsoChronology#INSTANCE} will be
+ * used.
+ */
+ public LocalDateTimeStringConverter(FormatStyle dateStyle, FormatStyle timeStyle,
+ Locale locale, Chronology chronology) {
+ ldtConverter = new LdtConverter(LocalDateTime.class, null, null,
+ dateStyle, timeStyle, locale, chronology);
+ }
+
+
+
+ // ------------------------------------------------------- Converter Methods
+
+ /** {@inheritDoc} */
+ @Override public LocalDateTime fromString(String value) {
+ return ldtConverter.fromString(value);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString(LocalDateTime value) {
+ return ldtConverter.toString(value);
+ }
+
+
+
+ static class LdtConverter extends StringConverter {
+ private Class type;
+ Locale locale;
+ Chronology chronology;
+ DateTimeFormatter formatter;
+ DateTimeFormatter parser;
+ FormatStyle dateStyle;
+ FormatStyle timeStyle;
+
+ LdtConverter(Class type, DateTimeFormatter formatter, DateTimeFormatter parser,
+ FormatStyle dateStyle, FormatStyle timeStyle, Locale locale, Chronology chronology) {
+ this.type = type;
+ this.formatter = formatter;
+ this.parser = (parser != null) ? parser : formatter;
+ this.locale = (locale != null) ? locale : Locale.getDefault(Locale.Category.FORMAT);
+ this.chronology = (chronology != null) ? chronology : IsoChronology.INSTANCE;
+
+ if (type == LocalDate.class || type == LocalDateTime.class) {
+ this.dateStyle = (dateStyle != null) ? dateStyle : FormatStyle.SHORT;
+ }
+
+ if (type == LocalTime.class || type == LocalDateTime.class) {
+ this.timeStyle = (timeStyle != null) ? timeStyle : FormatStyle.SHORT;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings({"unchecked"})
+ @Override public T fromString(String text) {
+ if (text == null || text.isEmpty()) {
+ return null;
+ }
+
+ text = text.trim();
+
+ if (parser == null) {
+ parser = getDefaultParser();
+ }
+
+ TemporalAccessor temporal = parser.parse(text);
+
+ if (type == LocalDate.class) {
+ return (T)LocalDate.from(chronology.date(temporal));
+ } else if (type == LocalTime.class) {
+ return (T)LocalTime.from(temporal);
+ } else {
+ return (T)LocalDateTime.from(chronology.localDateTime(temporal));
+ }
+ }
+
+
+ /** {@inheritDoc} */
+ @Override public String toString(T value) {
+ // If the specified value is null, return a zero-length String
+ if (value == null) {
+ return "";
+ }
+
+ if (formatter == null) {
+ formatter = getDefaultFormatter();
+ }
+
+ if (value instanceof LocalDate) {
+ ChronoLocalDate cDate;
+ try {
+ cDate = chronology.date(value);
+ } catch (DateTimeException ex) {
+ System.err.println(ex);
+ chronology = IsoChronology.INSTANCE;
+ cDate = (LocalDate)value;
+ }
+ return formatter.format(cDate);
+ } else if (value instanceof LocalDateTime) {
+ ChronoLocalDateTime extends ChronoLocalDate> cDateTime;
+ try {
+ cDateTime = chronology.localDateTime(value);
+ } catch (DateTimeException ex) {
+ System.err.println(ex);
+ chronology = IsoChronology.INSTANCE;
+ cDateTime = (LocalDateTime)value;
+ }
+ return formatter.format(cDateTime);
+ } else {
+ return formatter.format(value);
+ }
+ }
+
+
+ private DateTimeFormatter getDefaultParser() {
+ String pattern =
+ DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle,
+ chronology, locale);
+ return new DateTimeFormatterBuilder().parseLenient()
+ .appendPattern(pattern)
+ .toFormatter()
+ .withChronology(chronology)
+ .withDecimalStyle(DecimalStyle.of(locale));
+ }
+
+ /**
+ * Return a default DateTimeFormatter
instance to use for formatting
+ * and parsing in this {@link StringConverter}.
+ */
+ private DateTimeFormatter getDefaultFormatter() {
+ DateTimeFormatter formatter;
+
+ if (dateStyle != null && timeStyle != null) {
+ formatter = DateTimeFormatter.ofLocalizedDateTime(dateStyle, timeStyle);
+ } else if (dateStyle != null) {
+ formatter = DateTimeFormatter.ofLocalizedDate(dateStyle);
+ } else {
+ formatter = DateTimeFormatter.ofLocalizedTime(timeStyle);
+ }
+
+ formatter = formatter.withLocale(locale)
+ .withChronology(chronology)
+ .withDecimalStyle(DecimalStyle.of(locale));
+
+ if (dateStyle != null) {
+ formatter = fixFourDigitYear(formatter, dateStyle, timeStyle,
+ chronology, locale);
+ }
+
+ return formatter;
+ }
+
+ private DateTimeFormatter fixFourDigitYear(DateTimeFormatter formatter,
+ FormatStyle dateStyle, FormatStyle timeStyle,
+ Chronology chronology, Locale locale) {
+ String pattern =
+ DateTimeFormatterBuilder.getLocalizedDateTimePattern(dateStyle, timeStyle,
+ chronology, locale);
+ if (pattern.contains("yy") && !pattern.contains("yyy")) {
+ // Modify pattern to show four-digit year, including leading zeros.
+ String newPattern = pattern.replace("yy", "yyyy");
+ formatter = DateTimeFormatter.ofPattern(newPattern)
+ .withDecimalStyle(DecimalStyle.of(locale));
+ }
+
+ return formatter;
+ }
+ }
+}
--- /dev/null 2014-07-27 19:38:16.499796011 -0700
+++ new/modules/base/src/main/java/javafx/util/converter/LocalTimeStringConverter.java 2014-08-04 16:58:39.567035703 -0700
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.util.converter;
+
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Locale;
+
+import javafx.util.StringConverter;
+import javafx.util.converter.LocalDateTimeStringConverter.LdtConverter;
+
+/**
+ * {@link StringConverter} implementation for {@link LocalTime} values.
+ *
+ * @see LocalDateStringConverter
+ * @see LocalDateTimeStringConverter
+ * @since JavaFX 8u40
+ */
+public class LocalTimeStringConverter extends StringConverter {
+
+ LdtConverter ldtConverter;
+
+ // ------------------------------------------------------------ Constructors
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalTime} values, using a
+ * default formatter and parser with {@link FormatStyle#SHORT}, and the
+ * user's {@link Locale}.
+ */
+ public LocalTimeStringConverter() {
+ ldtConverter = new LdtConverter(LocalTime.class, null, null,
+ null, null, null, null);
+ }
+
+ /**
+ * Create a {@link StringConverter} for {@link LocalTime} values, using a
+ * default formatter and parser with the specified {@link FormatStyle} and
+ * based on the user's {@link Locale}.
+ *
+ * @param timeStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser. If null then {@link FormatStyle#SHORT} will be used.
+ */
+ public LocalTimeStringConverter(FormatStyle timeStyle) {
+ ldtConverter = new LdtConverter(LocalTime.class, null, null,
+ null, timeStyle, null, null);
+ }
+
+ /**
+ * Create a StringConverter for {@link LocalTime} values, using a
+ * default formatter and parser with the specified {@link FormatStyle}
+ * and {@link Locale}.
+ *
+ * @param timeStyle The {@link FormatStyle} that will be used by the default
+ * formatter and parser. If null then {@link FormatStyle#SHORT} will be used.
+ * @param locale The {@link Locale} that will be used by the default
+ * formatter and parser. If null then
+ * {@code Locale.getDefault(Locale.Category.FORMAT)} will be used.
+ */
+ public LocalTimeStringConverter(FormatStyle timeStyle, Locale locale) {
+ ldtConverter = new LdtConverter(LocalTime.class, null, null,
+ null, timeStyle, locale, null);
+ }
+
+ /**
+ * Create a StringConverter for {@link LocalTime} values using the
+ * supplied formatter and parser, which are responsible for
+ * choosing the desired {@link Locale}.
+ *
+ * For example, a fixed pattern can be used for converting both ways:
+ *
+ * String pattern = "HH:mm:ss";
+ * DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+ * StringConverter converter =
+ * DateTimeStringConverter.getLocalTimeConverter(formatter, null);
+ *
+ *
+ * @param formatter An instance of {@link DateTimeFormatter} which
+ * will be used for formatting by the toString() method. If null
+ * then a default formatter will be used.
+ * @param parser An instance of {@link DateTimeFormatter} which
+ * will be used for parsing by the fromString() method. This can
+ * be identical to formatter. If null, then formatter will be
+ * used, and if that is also null, then a default parser will be
+ * used.
+ */
+ public LocalTimeStringConverter(DateTimeFormatter formatter, DateTimeFormatter parser) {
+ ldtConverter = new LdtConverter(LocalTime.class, formatter, parser,
+ null, null, null, null);
+ }
+
+ // ------------------------------------------------------- Converter Methods
+
+ /** {@inheritDoc} */
+ @Override public LocalTime fromString(String value) {
+ return ldtConverter.fromString(value);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString(LocalTime value) {
+ return ldtConverter.toString(value);
+ }
+}
--- /dev/null 2014-07-27 19:38:16.499796011 -0700
+++ new/modules/base/src/test/java/javafx/util/converter/LocalDateStringConverterTest.java 2014-08-04 16:58:40.283035709 -0700
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.util.converter;
+
+import java.util.Arrays;
+import java.time.LocalDate;
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Collection;
+import java.util.Locale;
+
+import javafx.util.StringConverter;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ */
+@RunWith(Parameterized.class)
+public class LocalDateStringConverterTest {
+ private static final LocalDate VALID_DATE = LocalDate.of(1985, 1, 12);
+
+ private static final DateTimeFormatter aFormatter = DateTimeFormatter.ofPattern("dd MM yyyy");
+ private static final DateTimeFormatter aParser = DateTimeFormatter.ofPattern("yyyy MM dd");
+
+
+ @Parameterized.Parameters public static Collection implementations() {
+ return Arrays.asList(new Object[][] {
+ { new LocalDateStringConverter(),
+ Locale.getDefault(Locale.Category.FORMAT), FormatStyle.SHORT,
+ VALID_DATE, null, null },
+
+ { new LocalDateStringConverter(aFormatter, aParser),
+ Locale.getDefault(Locale.Category.FORMAT), null,
+ VALID_DATE, aFormatter, aParser },
+
+ { new LocalDateStringConverter(FormatStyle.SHORT, Locale.UK, IsoChronology.INSTANCE),
+ Locale.UK, FormatStyle.SHORT,
+ VALID_DATE, null, null },
+ });
+ }
+
+ private LocalDateStringConverter converter;
+ private Locale locale;
+ private FormatStyle dateStyle;
+ private DateTimeFormatter formatter, parser;
+ private LocalDate validDate;
+
+ public LocalDateStringConverterTest(LocalDateStringConverter converter, Locale locale, FormatStyle dateStyle, LocalDate validDate, DateTimeFormatter formatter, DateTimeFormatter parser) {
+ this.converter = converter;
+ this.locale = locale;
+ this.dateStyle = dateStyle;
+ this.validDate = validDate;
+ this.formatter = formatter;
+ this.parser = parser;
+ }
+
+ @Before public void setup() {
+ }
+
+ /*********************************************************************
+ * Test constructors
+ ********************************************************************/
+
+ @Test public void testConstructor() {
+ assertEquals(locale, converter.ldtConverter.locale);
+ assertEquals((dateStyle != null) ? dateStyle : FormatStyle.SHORT, converter.ldtConverter.dateStyle);
+ assertNull(converter.ldtConverter.timeStyle);
+ if (formatter != null) {
+ assertEquals(formatter, converter.ldtConverter.formatter);
+ }
+ if (parser != null) {
+ assertEquals(parser, converter.ldtConverter.parser);
+ } else if (formatter != null) {
+ assertEquals(formatter, converter.ldtConverter.parser);
+ }
+ }
+
+
+ /*********************************************************************
+ * Test toString / fromString methods
+ ********************************************************************/
+
+ @Test public void toString_to_fromString_testRoundtrip() {
+ if (formatter == null) {
+ // Only the default formatter/parser can guarantee roundtrip symmetry
+ assertEquals(validDate, converter.fromString(converter.toString(validDate)));
+ }
+ }
+
+ @Test(expected=RuntimeException.class)
+ public void fromString_testInvalidInput() {
+ converter.fromString("abcdefg");
+ }
+}
--- /dev/null 2014-07-27 19:38:16.499796011 -0700
+++ new/modules/base/src/test/java/javafx/util/converter/LocalDateTimeStringConverterTest.java 2014-08-04 16:58:40.983035715 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.util.converter;
+
+import java.time.LocalDateTime;
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Locale;
+import static org.junit.Assert.*;
+
+import javafx.util.StringConverter;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.Ignore;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ */
+@RunWith(Parameterized.class)
+public class LocalDateTimeStringConverterTest {
+ private static final LocalDateTime VALID_LDT_WITH_SECONDS = LocalDateTime.of(1985, 1, 12, 12, 34, 56);
+ private static final LocalDateTime VALID_LDT_WITHOUT_SECONDS = LocalDateTime.of(1985, 1, 12, 12, 34, 0);
+
+ private static final DateTimeFormatter aFormatter = DateTimeFormatter.ofPattern("dd MM yyyy HH mm ss");
+ private static final DateTimeFormatter aParser = DateTimeFormatter.ofPattern("yyyy MM dd hh mm ss a");
+
+ @Parameterized.Parameters public static Collection implementations() {
+ return Arrays.asList(new Object[][] {
+ { new LocalDateTimeStringConverter(),
+ Locale.getDefault(Locale.Category.FORMAT), FormatStyle.SHORT, FormatStyle.SHORT,
+ VALID_LDT_WITHOUT_SECONDS, null, null },
+
+ { new LocalDateTimeStringConverter(aFormatter, aParser),
+ Locale.getDefault(Locale.Category.FORMAT), null, null,
+ VALID_LDT_WITH_SECONDS, aFormatter, aParser },
+
+ { new LocalDateTimeStringConverter(FormatStyle.SHORT, FormatStyle.SHORT, Locale.UK, IsoChronology.INSTANCE),
+ Locale.UK, FormatStyle.SHORT, FormatStyle.SHORT,
+ VALID_LDT_WITHOUT_SECONDS, null, null },
+ });
+ }
+
+ private LocalDateTimeStringConverter converter;
+ private Locale locale;
+ private FormatStyle dateStyle;
+ private FormatStyle timeStyle;
+ private DateTimeFormatter formatter, parser;
+
+ private LocalDateTime validDateTime;
+
+ public LocalDateTimeStringConverterTest(LocalDateTimeStringConverter converter, Locale locale, FormatStyle dateStyle, FormatStyle timeStyle, LocalDateTime validDateTime, DateTimeFormatter formatter, DateTimeFormatter parser) {
+ this.converter = converter;
+ this.locale = locale;
+ this.dateStyle = dateStyle;
+ this.timeStyle = timeStyle;
+ this.validDateTime = validDateTime;
+ this.formatter = formatter;
+ this.parser = parser;
+ }
+
+ @Before public void setup() {
+ }
+
+ /*********************************************************************
+ * Test constructors
+ ********************************************************************/
+
+ @Test public void testConstructor() {
+ assertEquals(locale, converter.ldtConverter.locale);
+ assertEquals((dateStyle != null) ? dateStyle : FormatStyle.SHORT, converter.ldtConverter.dateStyle);
+ assertEquals((timeStyle != null) ? timeStyle : FormatStyle.SHORT, converter.ldtConverter.timeStyle);
+ if (formatter != null) {
+ assertEquals(formatter, converter.ldtConverter.formatter);
+ }
+ if (parser != null) {
+ assertEquals(parser, converter.ldtConverter.parser);
+ } else if (formatter != null) {
+ assertEquals(formatter, converter.ldtConverter.parser);
+ }
+ }
+
+
+ /*********************************************************************
+ * Test toString / fromString methods
+ ********************************************************************/
+
+ @Test public void toString_to_fromString_testRoundtrip() {
+ if (formatter == null) {
+ // Only the default formatter/parser can guarantee roundtrip symmetry
+ assertEquals(validDateTime, converter.fromString(converter.toString(validDateTime)));
+ }
+ }
+
+
+ @Test(expected=RuntimeException.class)
+ public void fromString_testInvalidInput() {
+ converter.fromString("abcdefg");
+ }
+
+ @Test public void converter_with_specified_formatter_and_parser() {
+ String formatPattern = "dd MMMM yyyy, HH:mm:ss";
+ String parsePattern = "MMMM dd, yyyy, HH:mm:ss";
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern(formatPattern);
+ DateTimeFormatter parser = DateTimeFormatter.ofPattern(parsePattern);
+ StringConverter converter = new LocalDateTimeStringConverter(formatter, parser);
+ assertEquals("12 January 1985, 12:34:56", converter.toString(VALID_LDT_WITH_SECONDS));
+ assertEquals(VALID_LDT_WITH_SECONDS, converter.fromString("January 12, 1985, 12:34:56"));
+ }
+
+ @Test public void converter_with_specified_formatter_and_null_parser() {
+ String pattern = "dd MMMM yyyy, HH:mm:ss";
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
+ StringConverter converter = new LocalDateTimeStringConverter(formatter, null);
+ assertEquals("12 January 1985, 12:34:56", converter.toString(VALID_LDT_WITH_SECONDS));
+ assertEquals(VALID_LDT_WITH_SECONDS, converter.fromString("12 January 1985, 12:34:56"));
+ }
+}
--- /dev/null 2014-07-27 19:38:16.499796011 -0700
+++ new/modules/base/src/test/java/javafx/util/converter/LocalTimeStringConverterTest.java 2014-08-04 16:58:41.719035721 -0700
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2014, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javafx.util.converter;
+
+import java.time.LocalTime;
+import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Locale;
+
+import javafx.util.StringConverter;
+
+import static org.junit.Assert.*;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+/**
+ */
+@RunWith(Parameterized.class)
+public class LocalTimeStringConverterTest {
+ private static final LocalTime VALID_TIME_WITH_SECONDS;
+ private static final LocalTime VALID_TIME_WITHOUT_SECONDS;
+
+ static {
+ VALID_TIME_WITH_SECONDS = LocalTime.of(12, 34, 56);
+ VALID_TIME_WITHOUT_SECONDS = LocalTime.of(12, 34, 0);
+ }
+
+ private static final DateTimeFormatter aFormatter = DateTimeFormatter.ofPattern("HH mm ss");
+ private static final DateTimeFormatter aParser = DateTimeFormatter.ofPattern("hh mm ss a");
+
+
+ @Parameterized.Parameters public static Collection implementations() {
+ return Arrays.asList(new Object[][] {
+ { new LocalTimeStringConverter(),
+ Locale.getDefault(Locale.Category.FORMAT), FormatStyle.SHORT,
+ VALID_TIME_WITHOUT_SECONDS, null, null },
+
+ { new LocalTimeStringConverter(aFormatter, aParser),
+ Locale.getDefault(Locale.Category.FORMAT), null,
+ VALID_TIME_WITH_SECONDS, aFormatter, aParser },
+
+ { new LocalTimeStringConverter(FormatStyle.SHORT, Locale.UK),
+ Locale.UK, FormatStyle.SHORT,
+ VALID_TIME_WITHOUT_SECONDS, null, null },
+ });
+ }
+
+ private LocalTimeStringConverter converter;
+ private Locale locale;
+ private FormatStyle timeStyle;
+ private DateTimeFormatter formatter, parser;
+ private LocalTime validTime;
+
+ public LocalTimeStringConverterTest(LocalTimeStringConverter converter, Locale locale, FormatStyle timeStyle, LocalTime validTime, DateTimeFormatter formatter, DateTimeFormatter parser) {
+ this.converter = converter;
+ this.locale = locale;
+ this.timeStyle = timeStyle;
+ this.validTime = validTime;
+ this.formatter = formatter;
+ this.parser = parser;
+ }
+
+ @Before public void setup() {
+ }
+
+ /*********************************************************************
+ * Test constructors
+ ********************************************************************/
+
+ @Test public void testConstructor() {
+ assertEquals(locale, converter.ldtConverter.locale);
+ assertNull(converter.ldtConverter.dateStyle);
+ assertEquals((timeStyle != null) ? timeStyle : FormatStyle.SHORT, converter.ldtConverter.timeStyle);
+ if (formatter != null) {
+ assertEquals(formatter, converter.ldtConverter.formatter);
+ }
+ if (parser != null) {
+ assertEquals(parser, converter.ldtConverter.parser);
+ } else if (formatter != null) {
+ assertEquals(formatter, converter.ldtConverter.parser);
+ }
+ }
+
+
+
+ /*********************************************************************
+ * Test toString / fromString methods
+ ********************************************************************/
+
+ @Test public void toString_to_fromString_testRoundtrip() {
+ if (formatter == null) {
+ // Only the default formatter/parser can guarantee roundtrip symmetry
+ assertEquals(validTime, converter.fromString(converter.toString(validTime)));
+ }
+ }
+
+ @Test(expected=RuntimeException.class)
+ public void fromString_testInvalidInput() {
+ converter.fromString("abcdefg");
+ }
+}