You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/01/03 19:57:06 UTC

[isis] branch master updated: ISIS-2882: configurable canonical temporal parsing (UI)

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 7eaa035  ISIS-2882: configurable canonical temporal parsing (UI)
7eaa035 is described below

commit 7eaa03520145e34cb2525391e7aceeeeddfd147d
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Jan 3 20:56:56 2022 +0100

    ISIS-2882: configurable canonical temporal parsing (UI)
---
 .../modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc |   4 +-
 .../value/semantics/TemporalValueSemantics.java    |  79 +++++
 .../value/semantics/ValueSemanticsAbstract.java    |  32 +-
 .../apache/isis/core/config/IsisConfiguration.java | 358 +--------------------
 .../temporal/TemporalValueSemanticsProvider.java   |  72 ++++-
 .../JavaUtilDateValueSemanticsProviderTest.java    |  50 ++-
 .../wicket/model/isis/WicketViewerSettings.java    |  10 -
 .../services/WicketViewerSettingsDefault.java      |  10 -
 8 files changed, 199 insertions(+), 416 deletions(-)

diff --git a/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc b/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
index cd5589a..ccc69eb 100644
--- a/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
+++ b/antora/components/relnotes/modules/ROOT/pages/2021/2.0.0-M7/mignotes.adoc
@@ -153,12 +153,12 @@ or globally via `ValueSemanticsProvider<org.joda.time.DateTime>`
 
 | `isis.viewer.wicket.date-pattern` (removed)
 | defaults to (canonical) `yyyy-MM-dd` editing format,
-use `isis.value-types.temporal.date-pattern` instead or
+use `isis.value-types.temporal.editing.date-pattern` instead or
 customize via `ValueSemanticsProvider<T>`
 
 | `isis.viewer.wicket.date-time-pattern` (removed)
 | defaults to concatenation of `date-pattern` with a blank `" "` and with a `time-pattern` editing format,
-use `isis.value-types.temporal.*-pattern` instead or
+use `isis.value-types.temporal.editing.*-pattern` instead or
 customize via `ValueSemanticsProvider<T>`
 
 |===
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java
index 33fb86d..bf0a285 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/TemporalValueSemantics.java
@@ -21,6 +21,15 @@ package org.apache.isis.applib.value.semantics;
 import java.time.Duration;
 import java.time.temporal.Temporal;
 
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+
+import lombok.Data;
+import lombok.NonNull;
+import lombok.val;
+
 /**
  * Common base for {@link java.time.temporal.Temporal} value types.
  *
@@ -71,4 +80,74 @@ extends
     TemporalCharacteristic getTemporalCharacteristic();
     OffsetCharacteristic getOffsetCharacteristic();
 
+    @Data
+    public static class TemporalEditingPattern {
+
+        /**
+         * The locale-independent (canonical) pattern used for editing dates in the UI.
+         */
+        @NotNull @NotEmpty
+        private String datePattern = "yyyy-MM-dd";
+
+        /**
+         * The locale-independent (canonical) pattern used for editing time in the UI.
+         * <p>
+         * When editing, omitting nano-seconds, seconds or minutes will use zeros instead.
+         */
+        @NotNull @NotEmpty
+        private String timePattern = "HH:mm:ss"; //FIXME[ISIS-2882] support omitted parts on input "HH[:mm[:ss[.SSSSSSSSS]]]"
+
+        /**
+         * The locale-independent (canonical) pattern used for editing time-zone in the UI.
+         */
+        @NotNull @NotEmpty
+        private String zonePattern = "x";
+
+        /**
+         * The locale-independent (canonical) pattern used for editing date and time in the UI.
+         * <p>
+         * Uses {@code String.format(dateTimeJoiningPattern, datePattern, timePattern)}
+         * to interpolate the effective date-time format.
+         * @see String#format(String, Object...)
+         */
+        @NotNull @NotEmpty
+        private String dateTimeJoiningPattern = "%1$s %2$s";
+
+        /**
+         * The locale-independent (canonical) pattern used for editing zoned temporals
+         * (date, time or date-time) in the UI.
+         * <p>
+         * Uses {@code String.format(zoneJoiningPattern, temporalPattern, zonePattern)}
+         * to interpolate the effective zoned temporal format.
+         * @see String#format(String, Object...)
+         */
+        @NotNull @NotEmpty
+        private String zoneJoiningPattern = "%1$s %2$s";
+
+        public String getEditingFormatAsPattern(
+                final @NonNull TemporalCharacteristic temporalCharacteristic,
+                final @NonNull OffsetCharacteristic offsetCharacteristic) {
+
+            switch (temporalCharacteristic) {
+            case DATE_TIME:
+                val dateTimePattern =
+                    String.format(getDateTimeJoiningPattern(), getDatePattern(), getTimePattern());
+                return offsetCharacteristic.isLocal()
+                        ? dateTimePattern
+                        : String.format(getZoneJoiningPattern(), dateTimePattern, getZonePattern());
+            case DATE_ONLY:
+                return offsetCharacteristic.isLocal()
+                        ? getDatePattern()
+                        : String.format(getZoneJoiningPattern(), getDatePattern(), getZonePattern());
+            case TIME_ONLY:
+                return offsetCharacteristic.isLocal()
+                        ? getTimePattern()
+                        : String.format(getZoneJoiningPattern(), getTimePattern(), getZonePattern());
+            default:
+                throw _Exceptions.unmatchedCase(temporalCharacteristic);
+            }
+        }
+
+    }
+
 }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
index 112e836..3d1fc16 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
@@ -36,6 +36,7 @@ import org.springframework.lang.Nullable;
 import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
 import org.apache.isis.applib.locale.UserLocale;
 import org.apache.isis.applib.services.iactnlayer.InteractionContext;
+import org.apache.isis.applib.value.semantics.TemporalValueSemantics.TemporalEditingPattern;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
@@ -214,12 +215,10 @@ implements
             final @Nullable ValueSemanticsProvider.Context context,
             final @NonNull TemporalValueSemantics.TemporalCharacteristic temporalCharacteristic,
             final @NonNull TemporalValueSemantics.OffsetCharacteristic offsetCharacteristic,
-            final @NonNull String datePattern,
-            final @NonNull String timePattern,
-            final @NonNull String zonePattern) {
+            final @NonNull TemporalEditingPattern editingPattern) {
 
         return getEditingFormatAsBuilder(
-                temporalCharacteristic, offsetCharacteristic, datePattern, timePattern, zonePattern)
+                temporalCharacteristic, offsetCharacteristic, editingPattern)
                 .parseLenient()
                 .parseCaseInsensitive()
                 .toFormatter(getUserLocale(context).getTimeFormatLocale());
@@ -228,34 +227,33 @@ implements
     protected DateTimeFormatterBuilder getEditingFormatAsBuilder(
             final @NonNull TemporalValueSemantics.TemporalCharacteristic temporalCharacteristic,
             final @NonNull TemporalValueSemantics.OffsetCharacteristic offsetCharacteristic,
-            final @NonNull String datePattern,
-            final @NonNull String timePattern,
-            final @NonNull String zonePattern) {
+            final @NonNull TemporalEditingPattern editingPattern) {
 
         return new DateTimeFormatterBuilder()
-            .appendPattern(getEditingFormatAsPattern(temporalCharacteristic, offsetCharacteristic, datePattern, timePattern, zonePattern));
+            .appendPattern(getEditingFormatAsPattern(
+                    temporalCharacteristic, offsetCharacteristic, editingPattern));
     }
 
     protected String getEditingFormatAsPattern(
             final @NonNull TemporalValueSemantics.TemporalCharacteristic temporalCharacteristic,
             final @NonNull TemporalValueSemantics.OffsetCharacteristic offsetCharacteristic,
-            final @NonNull String datePattern,
-            final @NonNull String timePattern,
-            final @NonNull String zonePattern) {
+            final @NonNull TemporalEditingPattern editingPattern) {
 
         switch (temporalCharacteristic) {
         case DATE_TIME:
+            val dateTimePattern =
+                String.format(editingPattern.getDateTimeJoiningPattern(), editingPattern.getDatePattern(), editingPattern.getTimePattern());
             return offsetCharacteristic.isLocal()
-                    ? datePattern + " " + timePattern
-                    : datePattern + " " + timePattern + " " + zonePattern;
+                    ? dateTimePattern
+                    : String.format(editingPattern.getZoneJoiningPattern(), dateTimePattern, editingPattern.getZonePattern());
         case DATE_ONLY:
             return offsetCharacteristic.isLocal()
-                    ? datePattern
-                    : datePattern + " " + zonePattern;
+                    ? editingPattern.getDatePattern()
+                    : String.format(editingPattern.getZoneJoiningPattern(), editingPattern.getDatePattern(), editingPattern.getZonePattern());
         case TIME_ONLY:
             return offsetCharacteristic.isLocal()
-                    ? timePattern
-                    : timePattern + " " + zonePattern;
+                    ? editingPattern.getTimePattern()
+                    : String.format(editingPattern.getZoneJoiningPattern(), editingPattern.getTimePattern(), editingPattern.getZonePattern());
         default:
             throw _Exceptions.unmatchedCase(temporalCharacteristic);
         }
diff --git a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
index dc6b3a6..3703d22 100644
--- a/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
+++ b/core/config/src/main/java/org/apache/isis/core/config/IsisConfiguration.java
@@ -66,9 +66,10 @@ import org.apache.isis.applib.services.publishing.spi.EntityPropertyChangeSubscr
 import org.apache.isis.applib.services.userreg.EmailNotificationService;
 import org.apache.isis.applib.services.userreg.UserRegistrationService;
 import org.apache.isis.applib.services.userui.UserMenu;
+import org.apache.isis.applib.value.semantics.TemporalValueSemantics.TemporalEditingPattern;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.context._Context;
-import org.apache.isis.core.config.IsisConfiguration.Viewer;
+import org.apache.isis.core.config.IsisConfiguration.Core;
 import org.apache.isis.core.config.metamodel.facets.DefaultViewConfiguration;
 import org.apache.isis.core.config.metamodel.facets.EditingObjectsConfiguration;
 import org.apache.isis.core.config.metamodel.facets.PublishingPolicies.ActionPublishingPolicy;
@@ -78,12 +79,6 @@ import org.apache.isis.core.config.metamodel.services.ApplicationFeaturesInitCon
 import org.apache.isis.core.config.metamodel.specloader.IntrospectionMode;
 import org.apache.isis.core.config.viewer.web.DialogMode;
 
-import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
 import lombok.Data;
 import lombok.Getter;
 import lombok.Setter;
@@ -1936,34 +1931,6 @@ public class IsisConfiguration {
             private boolean clearOriginalDestination = false;
 
             /**
-             * The pattern used for rendering and parsing dates.
-             *
-             * <p>
-             * Each Date scalar panel will use {@link #getDatePattern()} or {@link #getDateTimePattern()} depending on its
-             * date type.  In the case of panels with a date picker, the pattern will be dynamically adjusted so that it can be
-             * used by the <a href="https://github.com/Eonasdan/bootstrap-datetimepicker">Bootstrap Datetime Picker</a>
-             * component (which uses <a href="http://momentjs.com/docs/#/parsing/string-format/">Moment.js formats</a>, rather
-             * than those of regular Java code).
-             */
-            @NotNull @NotEmpty
-            private String datePattern = "dd-MM-yyyy";
-
-            /**
-             * The pattern used for rendering and parsing date/times.
-             *
-             * <p>
-             * Each Date scalar panel will use {@link #getDatePattern()} or {@link #getDateTimePattern()}
-             * depending on its date type.  In the case of panels with a date time picker, the pattern will be
-             * dynamically adjusted so that it can be
-             * used by the <a href="https://github.com/Eonasdan/bootstrap-datetimepicker">Bootstrap Datetime Picker</a>
-             * component (which uses <a href="http://momentjs.com/docs/#/parsing/string-format/">Moment.js formats</a>, rather
-             * than those of regular Java code).
-             * </p>
-             */
-            @NotNull @NotEmpty
-            private String dateTimePattern = "dd-MM-yyyy HH:mm";
-
-            /**
              * Whether the dialog mode rendered when invoking actions on domain objects should be to use
              * the sidebar (the default) or to use a modal dialog.
              *
@@ -2573,295 +2540,14 @@ public class IsisConfiguration {
     @Data
     public static class ValueTypes {
 
-        private final Primitives primitives = new Primitives();
-        @Data
-        public static class Primitives {
-
-            // capitalized to avoid clash with keyword
-            private final Int Int = new Int();
-            @Data
-            public static class Int {
-                /**
-                 * Configures the number format understood by <code>IntValueSemanticsProviderAbstract</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
-        }
-
-        private final JavaLang javaLang = new JavaLang();
+        private final Temporal temporal = new Temporal();
         @Data
-        public static class JavaLang {
-
-            // capitalized to avoid clash with keyword
-            private final Byte Byte = new Byte();
-            @Data
-            public static class Byte {
-                /**
-                 * Configures the number format understood by <code>ByteValueSemanticsProviderAbstract</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
-
-            // capitalized to avoid clash with keyword
-            private final Double Double = new Double();
-            @Data
-            public static class Double {
-                /**
-                 * Configures the number format understood by <code>DoubleValueSemanticsProviderAbstract</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
+        public static class Temporal {
 
-            // capitalized to avoid clash with keyword
-            private final Float Float = new Float();
-            @Data
-            public static class Float {
-                /**
-                 * Configures the number format understood by <code>FloatValueSemanticsProviderAbstract</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
+            private final TemporalEditingPattern editing = new TemporalEditingPattern();
 
-            // capitalized to avoid clash with keyword
-            private final Long Long = new Long();
-            @Data
-            public static class Long {
-                /**
-                 * Configures the number format understood by <code>LongValueSemanticsProviderAbstract</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
-
-            // capitalized to avoid clash with keyword
-            private final Short Short = new Short();
-            @Data
-            public static class Short {
-                /**
-                 * Configures the number format understood by <code>ShortValueSemanticsProviderAbstract</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
         }
 
-        private final JavaMath javaMath = new JavaMath();
-        @Data
-        public static class JavaMath {
-            private final BigInteger bigInteger = new BigInteger();
-            @Data
-            public static class BigInteger {
-                /**
-                 * Configures the number format understood by <code>BigIntegerValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
-
-            private final BigDecimal bigDecimal = new BigDecimal();
-            @Data
-            public static class BigDecimal {
-                /**
-                 * Configures the number format understood by <code>BigDecimalValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
-        }
-
-        private final JavaTime javaTime = new JavaTime();
-        @Data
-        public static class JavaTime {
-            private final LocalDateTime localDateTime = new LocalDateTime();
-            @Data
-            public static class LocalDateTime {
-                /**
-                 * Configures the formats understood by <code>LocalDateTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-            private final OffsetDateTime offsetDateTime = new OffsetDateTime();
-            @Data
-            public static class OffsetDateTime {
-                /**
-                 * Configures the formats understood by <code>OffsetDateTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-            private final OffsetTime offsetTime = new OffsetTime();
-            @Data
-            public static class OffsetTime {
-                /**
-                 * Configures the formats understood by <code>OffsetTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-            private final LocalDate localDate = new LocalDate();
-            @Data
-            public static class LocalDate {
-                /**
-                 * Configures the formats understood by <code>LocalDateValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-            private final LocalTime localTime = new LocalTime();
-            @Data
-            public static class LocalTime {
-                /**
-                 * Configures the formats understood by <code>LocalTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-            private final ZonedDateTime zonedDateTime = new ZonedDateTime();
-            @Data
-            public static class ZonedDateTime {
-                /**
-                 * Configures the formats understood by <code>ZonedDateTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-        }
-
-        private final JavaUtil javaUtil = new JavaUtil();
-        @Data
-        public static class JavaUtil {
-
-            private final Date date = new Date();
-            @Data
-            public static class Date {
-                /**
-                 * Configures the formats understood by <code>JavaUtilDateValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-        }
-
-        private final JavaSql javaSql = new JavaSql();
-        @Data
-        public static class JavaSql {
-            private final Date date = new Date();
-            @Data
-            public static class Date {
-                /**
-                 * Configures the formats understood by <code>JavaSqlDateValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-            private final Time time = new Time();
-            @Data
-            public static class Time {
-                /**
-                 * Configures the formats understood by <code>JavaSqlTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "short";
-            }
-
-            private final Timestamp timestamp = new Timestamp();
-            @Data
-            public static class Timestamp {
-                /**
-                 * Configures the formats understood by <code>JavaSqlTimeStampValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "short";
-            }
-
-        }
-
-        private final Joda joda = new Joda();
-        @Data
-        public static class Joda {
-            private final LocalDateTime localDateTime = new LocalDateTime();
-            @Data
-            public static class LocalDateTime {
-                /**
-                 * Configures the formats understood by <code>JodaLocalDateTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-            private final LocalDate localDate = new LocalDate();
-            @Data
-            public static class LocalDate {
-                /**
-                 * Configures the formats understood by <code>JodaLocalDateValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-
-            private final DateTime dateTime = new DateTime();
-            @Data
-            public static class DateTime {
-                /**
-                 * Configures the formats understood by <code>JodaDateTimeValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format = "medium";
-            }
-        }
     }
 
     private final Testing testing = new Testing();
@@ -3023,40 +2709,6 @@ public class IsisConfiguration {
         }
     }
 
-    private final Legacy legacy = new Legacy();
-    @Data
-    public static class Legacy {
-
-        private final ValueTypes valueTypes = new ValueTypes();
-        @Data
-        public static class ValueTypes {
-            private final Percentage percentage = new Percentage();
-            @Data
-            public static class Percentage {
-                /**
-                 * Configures the formats understood by <code>PercentageValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private String format;
-            }
-
-            private final Money money = new Money();
-            @Data
-            public static class Money {
-                /**
-                 * Configures the default currency code used by <code>MoneyValueSemanticsProvider</code>.
-                 *
-                 * @deprecated
-                 */
-                @Deprecated
-                private Optional<String> currency = Optional.empty();
-            }
-        }
-    }
-
-
     private final Extensions extensions = new Extensions();
     @Data
     public static class Extensions {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java
index 9205ea2..67db9da 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/TemporalValueSemanticsProvider.java
@@ -29,18 +29,22 @@ import java.util.function.BiFunction;
 
 import javax.inject.Inject;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
 import org.apache.isis.applib.value.semantics.EncodingException;
 import org.apache.isis.applib.value.semantics.TemporalValueSemantics;
 import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
 import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.core.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.facets.objectvalue.temporalformatstyle.DateFormatStyleFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.temporalformatstyle.TimeFormatStyleFacet;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
 import lombok.Getter;
 import lombok.NonNull;
+import lombok.Value;
 import lombok.val;
 import lombok.experimental.Accessors;
 
@@ -56,7 +60,7 @@ public abstract class TemporalValueSemanticsProvider<T extends Temporal>
 extends ValueSemanticsAbstract<T>
 implements TemporalValueSemantics<T> {
 
-    @Inject protected SpecificationLoader specLoader;
+    @Inject protected MetaModelContext mmc;
 
     @Getter(onMethod_ = {@Override}) protected final TemporalCharacteristic temporalCharacteristic;
     @Getter(onMethod_ = {@Override}) protected final OffsetCharacteristic offsetCharacteristic;
@@ -186,21 +190,12 @@ implements TemporalValueSemantics<T> {
      */
     protected DateTimeFormatter getRenderingFormat(final ValueSemanticsProvider.Context context) {
 
-        val featureIfAny = Optional.ofNullable(specLoader) //JUnit support
-                .flatMap(specLdr->specLdr.loadFeature(context.getFeatureIdentifier()));
-
-        val dateFormatStyle = featureIfAny
-                .flatMap(feature->feature.lookupFacet(DateFormatStyleFacet.class))
-                .map(DateFormatStyleFacet::getDateFormatStyle)
-                .orElse(FormatStyle.MEDIUM);
-
-        val timeFormatStyle = featureIfAny
-                .flatMap(feature->feature.lookupFacet(TimeFormatStyleFacet.class))
-                .map(TimeFormatStyleFacet::getTimeFormatStyle)
-                .orElse(FormatStyle.MEDIUM);
+        val dateAndTimeFormatStyle = DateAndTimeFormatStyle.forContext(mmc, context);
 
         return getTemporalRenderingFormat(
-                context, temporalCharacteristic, offsetCharacteristic, dateFormatStyle, timeFormatStyle);
+                context, temporalCharacteristic, offsetCharacteristic,
+                dateAndTimeFormatStyle.getDateFormatStyle(),
+                dateAndTimeFormatStyle.getTimeFormatStyle());
     }
 
     /**
@@ -208,13 +203,13 @@ implements TemporalValueSemantics<T> {
      */
     protected DateTimeFormatter getEditingFormat(final ValueSemanticsProvider.Context context) {
         return getEditingFormat(context, temporalCharacteristic, offsetCharacteristic,
-                "yyyy-MM-dd", "HH:mm:ss", "x");
+                temporalEditingPattern());
     }
 
     @Override
     public String getPattern(final ValueSemanticsProvider.Context context) {
         return getEditingFormatAsPattern(temporalCharacteristic, offsetCharacteristic,
-                "yyyy-MM-dd", "HH:mm:ss", "x");
+                temporalEditingPattern());
     }
 
     /**
@@ -224,5 +219,48 @@ implements TemporalValueSemantics<T> {
         return getTemporalIsoFormat(temporalCharacteristic, offsetCharacteristic);
     }
 
+    // -- HELPER
+
+    @Value(staticConstructor = "of")
+    static class DateAndTimeFormatStyle {
+        @Nullable FormatStyle dateFormatStyle;
+        @Nullable FormatStyle timeFormatStyle;
+
+        static DateAndTimeFormatStyle forContext(
+                final @Nullable MetaModelContext mmc, // nullable .. JUnit support
+                final @Nullable ValueSemanticsProvider.Context context) {
+
+            val featureIfAny = Optional.ofNullable(mmc)
+                    .map(MetaModelContext::getSpecificationLoader)
+                    .flatMap(specLoader->specLoader.loadFeature(
+                            Optional.ofNullable(context)
+                            .map(ValueSemanticsProvider.Context::getFeatureIdentifier)
+                            .orElse(null)));
+
+            val dateFormatStyle = featureIfAny
+                    .flatMap(feature->feature.lookupFacet(DateFormatStyleFacet.class))
+                    .map(DateFormatStyleFacet::getDateFormatStyle)
+                    .orElse(FormatStyle.MEDIUM);
+
+            val timeFormatStyle = featureIfAny
+                    .flatMap(feature->feature.lookupFacet(TimeFormatStyleFacet.class))
+                    .map(TimeFormatStyleFacet::getTimeFormatStyle)
+                    .orElse(FormatStyle.MEDIUM);
+
+            return of(dateFormatStyle, timeFormatStyle);
+        }
+
+    }
+
+    private org.apache.isis.core.config.IsisConfiguration.ValueTypes.Temporal temporalConfig() {
+        return Optional.ofNullable(mmc) // nullable .. JUnit support
+                .map(MetaModelContext::getConfiguration)
+                .map(conf->conf.getValueTypes().getTemporal())
+                .orElseGet(IsisConfiguration.ValueTypes.Temporal::new);
+    }
+
+    private TemporalEditingPattern temporalEditingPattern() {
+        return temporalConfig().getEditing();
+    }
 
 }
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java
index 56656b6..07bb8ca 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/JavaUtilDateValueSemanticsProviderTest.java
@@ -22,8 +22,12 @@ import java.time.LocalDateTime;
 import java.util.Locale;
 
 import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
 import org.apache.isis.applib.locale.UserLocale;
 import org.apache.isis.applib.services.iactnlayer.InteractionContext;
@@ -32,16 +36,13 @@ import org.apache.isis.applib.value.semantics.ValueSemanticsProvider.Context;
 import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalDateTimeValueSemantics;
 import org.apache.isis.core.metamodel.valuesemantics.temporal.legacy.JavaUtilDateValueSemantics;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.fail;
-
 import lombok.val;
 
 class JavaUtilDateValueSemanticsProviderTest
 extends ValueSemanticsProviderAbstractTestCase {
 
     @SuppressWarnings("deprecation")
-    private final java.util.Date date = new java.util.Date(2013-1900, 03-1, 13, 17, 59);
+    private final java.util.Date date = new java.util.Date(2013-1900, 03-1, 13, 17, 59, 03);
     private JavaUtilDateValueSemantics valueSemantics;
 
     @BeforeEach
@@ -75,14 +76,49 @@ extends ValueSemanticsProviderAbstractTestCase {
     @Test
     public void testRendering() {
         val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
-        assertEquals("Mar 13, 2013, 5:59:00 PM", valueSemantics.simpleTextPresentation(_context , date));
+        assertEquals("Mar 13, 2013, 5:59:03 PM", valueSemantics.simpleTextPresentation(_context , date));
+    }
+
+    //FIXME[ISIS-2882] support omitted parts on input
+    @Test @Disabled
+    public void testParseNoMinutes() throws Exception {
+        val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+        val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17");
+        assertEquals(date.getTime() - 3540_000L - 3000L, parsedDate.getTime());
+    }
+
+    //FIXME[ISIS-2882] support omitted parts on input
+    @Test @Disabled
+    public void testParseNoSeconds() throws Exception {
+        val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+        val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59");
+        assertEquals(date.getTime() - 3000L, parsedDate.getTime());
     }
 
     @Test
-    public void testParse() throws Exception {
+    public void testParseSeconds() throws Exception {
         val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
-        val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:00");
+        val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:03");
         assertEquals(date.getTime(), parsedDate.getTime());
     }
 
+    //FIXME[ISIS-2882] support omitted parts on input
+    /**
+     * @see https://stackoverflow.com/questions/30103167/jsr-310-parsing-seconds-fraction-with-variable-length
+     */
+    @Test @Disabled("cannot find a format pattern that can handle both millis and nanos")
+    public void testParseMillis() throws Exception {
+        val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+        val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:03.123");
+        assertEquals(date.getTime() + 123L, parsedDate.getTime());
+    }
+
+    //FIXME[ISIS-2882] support omitted parts on input
+    @Test @Disabled
+    public void testParseNanos() throws Exception {
+        val _context = Context.of(null, InteractionContext.builder().locale(UserLocale.valueOf(Locale.ENGLISH)).build());
+        val parsedDate = valueSemantics.parseTextRepresentation(_context, "2013-03-13 17:59:03.123456789");
+        assertEquals(date.getTime() + 123L, parsedDate.getTime());
+    }
+
 }
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java
index 6385718..b7d250b 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/isis/WicketViewerSettings.java
@@ -35,16 +35,6 @@ public interface WicketViewerSettings extends Serializable {
     int getMaxTitleLengthInParentedTables();
 
     /**
-     * As per {@link org.apache.isis.core.config.IsisConfiguration.Viewer.Wicket#setDatePattern(String)}
-     */
-    String getDatePattern();
-
-    /**
-     * As per {@link org.apache.isis.core.config.IsisConfiguration.Viewer.Wicket#setDateTimePattern(String)}
-     */
-    String getDateTimePattern();
-
-    /**
      * As per {@link org.apache.isis.core.config.IsisConfiguration.Viewer.Wicket#setReplaceDisabledTagWithReadonlyTag(boolean)}
      */
     boolean isReplaceDisabledTagWithReadonlyTag();
diff --git a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java
index 51d8058..b5f0901 100644
--- a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java
+++ b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/WicketViewerSettingsDefault.java
@@ -52,16 +52,6 @@ public class WicketViewerSettingsDefault implements WicketViewerSettings {
     }
 
     @Override
-    public String getDatePattern() {
-        return getConfiguration().getViewer().getWicket().getDatePattern();
-    }
-
-    @Override
-    public String getDateTimePattern() {
-        return getConfiguration().getViewer().getWicket().getDateTimePattern();
-    }
-
-    @Override
     public boolean isReplaceDisabledTagWithReadonlyTag() {
         return getConfiguration().getViewer().getWicket().isReplaceDisabledTagWithReadonlyTag();
     }