You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2021/12/15 17:16:43 UTC

[freemarker] 01/02: [FREEMARKER-35] Removed new settings that deal with the format of Temporal-s that could be treated as date, time, or date-time types. For those, use the same settings as for java.util.Date-s instead. (Will need more work though, as pattern syntax of SimpleDateFormat and DateTimeFormatter somewhat differs.)

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

ddekany pushed a commit to branch FREEMARKER-35
in repository https://gitbox.apache.org/repos/asf/freemarker.git

commit 4571e34876d0db0f9da3aad8f9ccf12dd578e34d
Author: ddekany <dd...@apache.org>
AuthorDate: Wed Dec 15 18:08:58 2021 +0100

    [FREEMARKER-35] Removed new settings that deal with the format of Temporal-s that could be treated as date, time, or date-time types. For those, use the same settings as for java.util.Date-s instead. (Will need more work though, as pattern syntax of SimpleDateFormat and DateTimeFormatter somewhat differs.)
---
 src/main/java/freemarker/core/Configurable.java    | 437 ++++-----------------
 src/main/java/freemarker/core/Environment.java     |   4 -
 .../core/JavaTemplateTemporalFormat.java           |   9 +-
 src/main/java/freemarker/core/PropertySetting.java |  16 +-
 .../freemarker/core/TemplateConfiguration.java     |  49 ---
 .../java/freemarker/core/_CoreTemporalUtils.java   |  25 +-
 .../freemarker/core/CoercionToTextualTest.java     |   1 -
 .../java/freemarker/core/CoreTemporalUtilTest.java |   4 +-
 .../freemarker/core/TemporalErrorMessagesTest.java |  17 +-
 .../java/freemarker/core/TemporalFormatTest.java   |  21 +-
 .../java/freemarker/core/TemporalFormatTest2.java  |   4 +-
 .../test/templatesuite/templates/temporal.ftl      |  13 +-
 12 files changed, 118 insertions(+), 482 deletions(-)

diff --git a/src/main/java/freemarker/core/Configurable.java b/src/main/java/freemarker/core/Configurable.java
index c62abfd..385ee87 100644
--- a/src/main/java/freemarker/core/Configurable.java
+++ b/src/main/java/freemarker/core/Configurable.java
@@ -33,11 +33,13 @@ import java.time.OffsetTime;
 import java.time.Year;
 import java.time.YearMonth;
 import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.time.format.FormatStyle;
 import java.time.temporal.Temporal;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -68,6 +70,7 @@ import freemarker.ext.beans.MemberAccessPolicy;
 import freemarker.template.AttemptExceptionReporter;
 import freemarker.template.Configuration;
 import freemarker.template.DefaultObjectWrapper;
+import freemarker.template.DefaultObjectWrapperBuilder;
 import freemarker.template.ObjectWrapper;
 import freemarker.template.SimpleObjectWrapper;
 import freemarker.template.Template;
@@ -157,34 +160,6 @@ public class Configurable {
     /** Alias to the {@code ..._SNAKE_CASE} variation due to backward compatibility constraints. */
     public static final String CUSTOM_TEMPORAL_FORMATS_KEY = CUSTOM_TEMPORAL_FORMATS_KEY_SNAKE_CASE;
 
-    public static final String INSTANT_FORMAT_KEY_SNAKE_CASE = "instant_format";
-    public static final String INSTANT_FORMAT_KEY_CAMEL_CASE = "instantFormat";
-    public static final String INSTANT_FORMAT_KEY = INSTANT_FORMAT_KEY_SNAKE_CASE;
-
-    public static final String LOCAL_DATE_FORMAT_KEY_SNAKE_CASE = "local_date_format";
-    public static final String LOCAL_DATE_FORMAT_KEY_CAMEL_CASE = "localDateFormat";
-    public static final String LOCAL_DATE_FORMAT_KEY = LOCAL_DATE_FORMAT_KEY_SNAKE_CASE;
-
-    public static final String LOCAL_DATE_TIME_FORMAT_KEY_SNAKE_CASE = "local_date_time_format";
-    public static final String LOCAL_DATE_TIME_FORMAT_KEY_CAMEL_CASE = "localDateTimeFormat";
-    public static final String LOCAL_DATE_TIME_FORMAT_KEY = LOCAL_DATE_TIME_FORMAT_KEY_SNAKE_CASE;
-
-    public static final String LOCAL_TIME_FORMAT_KEY_SNAKE_CASE = "local_time_format";
-    public static final String LOCAL_TIME_FORMAT_KEY_CAMEL_CASE = "localTimeFormat";
-    public static final String LOCAL_TIME_FORMAT_KEY = LOCAL_TIME_FORMAT_KEY_SNAKE_CASE;
-
-    public static final String OFFSET_DATE_TIME_FORMAT_KEY_SNAKE_CASE = "offset_date_time_format";
-    public static final String OFFSET_DATE_TIME_FORMAT_KEY_CAMEL_CASE = "offsetDateTimeFormat";
-    public static final String OFFSET_DATE_TIME_FORMAT_KEY = OFFSET_DATE_TIME_FORMAT_KEY_SNAKE_CASE;
-
-    public static final String OFFSET_TIME_FORMAT_KEY_SNAKE_CASE = "offset_time_format";
-    public static final String OFFSET_TIME_FORMAT_KEY_CAMEL_CASE = "offsetTimeFormat";
-    public static final String OFFSET_TIME_FORMAT_KEY = OFFSET_TIME_FORMAT_KEY_SNAKE_CASE;
-
-    public static final String ZONED_DATE_TIME_FORMAT_KEY_SNAKE_CASE = "zoned_date_time_format";
-    public static final String ZONED_DATE_TIME_FORMAT_KEY_CAMEL_CASE = "zonedDateTimeFormat";
-    public static final String ZONED_DATE_TIME_FORMAT_KEY = ZONED_DATE_TIME_FORMAT_KEY_SNAKE_CASE;
-
     public static final String YEAR_FORMAT_KEY_SNAKE_CASE = "year_format";
     public static final String YEAR_FORMAT_KEY_CAMEL_CASE = "yearFormat";
     public static final String YEAR_FORMAT_KEY = YEAR_FORMAT_KEY_SNAKE_CASE;
@@ -366,19 +341,13 @@ public class Configurable {
         CUSTOM_TEMPORAL_FORMATS_KEY_SNAKE_CASE,
         DATE_FORMAT_KEY_SNAKE_CASE,
         DATETIME_FORMAT_KEY_SNAKE_CASE,
-        INSTANT_FORMAT_KEY_SNAKE_CASE,
         LAZY_AUTO_IMPORTS_KEY_SNAKE_CASE,
         LAZY_IMPORTS_KEY_SNAKE_CASE,
-        LOCAL_DATE_FORMAT_KEY_SNAKE_CASE,
-        LOCAL_DATE_TIME_FORMAT_KEY_SNAKE_CASE,
-        LOCAL_TIME_FORMAT_KEY_SNAKE_CASE,
         LOCALE_KEY_SNAKE_CASE,
         LOG_TEMPLATE_EXCEPTIONS_KEY_SNAKE_CASE,
         NEW_BUILTIN_CLASS_RESOLVER_KEY_SNAKE_CASE,
         NUMBER_FORMAT_KEY_SNAKE_CASE,
         OBJECT_WRAPPER_KEY_SNAKE_CASE,
-        OFFSET_DATE_TIME_FORMAT_KEY_SNAKE_CASE,
-        OFFSET_TIME_FORMAT_KEY_SNAKE_CASE,
         OUTPUT_ENCODING_KEY_SNAKE_CASE,
         SHOW_ERROR_TIPS_KEY_SNAKE_CASE,
         SQL_DATE_AND_TIME_TIME_ZONE_KEY_SNAKE_CASE,
@@ -390,8 +359,7 @@ public class Configurable {
         URL_ESCAPING_CHARSET_KEY_SNAKE_CASE,
         WRAP_UNCHECKED_EXCEPTIONS_KEY_SNAKE_CASE,
         YEAR_FORMAT_KEY_SNAKE_CASE,
-        YEAR_MONTH_FORMAT_KEY_SNAKE_CASE,
-        ZONED_DATE_TIME_FORMAT_KEY_SNAKE_CASE
+        YEAR_MONTH_FORMAT_KEY_SNAKE_CASE
     };
 
     private static final String[] SETTING_NAMES_CAMEL_CASE = new String[] {
@@ -409,19 +377,13 @@ public class Configurable {
         CUSTOM_TEMPORAL_FORMATS_KEY_CAMEL_CASE,
         DATE_FORMAT_KEY_CAMEL_CASE,
         DATETIME_FORMAT_KEY_CAMEL_CASE,
-        INSTANT_FORMAT_KEY_CAMEL_CASE,
         LAZY_AUTO_IMPORTS_KEY_CAMEL_CASE,
         LAZY_IMPORTS_KEY_CAMEL_CASE,
-        LOCAL_DATE_FORMAT_KEY_CAMEL_CASE,
-        LOCAL_DATE_TIME_FORMAT_KEY_CAMEL_CASE,
-        LOCAL_TIME_FORMAT_KEY_CAMEL_CASE,
         LOCALE_KEY_CAMEL_CASE,
         LOG_TEMPLATE_EXCEPTIONS_KEY_CAMEL_CASE,
         NEW_BUILTIN_CLASS_RESOLVER_KEY_CAMEL_CASE,
         NUMBER_FORMAT_KEY_CAMEL_CASE,
         OBJECT_WRAPPER_KEY_CAMEL_CASE,
-        OFFSET_DATE_TIME_FORMAT_KEY_CAMEL_CASE,
-        OFFSET_TIME_FORMAT_KEY_CAMEL_CASE,
         OUTPUT_ENCODING_KEY_CAMEL_CASE,
         SHOW_ERROR_TIPS_KEY_CAMEL_CASE,
         SQL_DATE_AND_TIME_TIME_ZONE_KEY_CAMEL_CASE,
@@ -433,8 +395,7 @@ public class Configurable {
         URL_ESCAPING_CHARSET_KEY_CAMEL_CASE,
         WRAP_UNCHECKED_EXCEPTIONS_KEY_CAMEL_CASE,
         YEAR_FORMAT_KEY_CAMEL_CASE,
-        YEAR_MONTH_FORMAT_KEY_CAMEL_CASE,
-        ZONED_DATE_TIME_FORMAT_KEY_CAMEL_CASE
+        YEAR_MONTH_FORMAT_KEY_CAMEL_CASE
     };
 
     private Configurable parent;
@@ -446,13 +407,6 @@ public class Configurable {
     private String timeFormat;
     private String dateFormat;
     private String dateTimeFormat;
-    private String instantFormat;
-    private String localDateFormat;
-    private String localDateTimeFormat;
-    private String localTimeFormat;
-    private String offsetDateTimeFormat;
-    private String offsetTimeFormat;
-    private String zonedDateTimeFormat;
     private String yearFormat;
     private String yearMonthFormat;
     private TimeZone timeZone;
@@ -528,27 +482,6 @@ public class Configurable {
         dateTimeFormat = "";
         properties.setProperty(DATETIME_FORMAT_KEY, dateTimeFormat);
         
-        instantFormat = JavaTemplateTemporalFormat.MEDIUM;
-        properties.setProperty(INSTANT_FORMAT_KEY, instantFormat);
-
-        localDateFormat = JavaTemplateTemporalFormat.MEDIUM;
-        properties.setProperty(LOCAL_DATE_FORMAT_KEY, localDateFormat);
-
-        localDateTimeFormat = JavaTemplateTemporalFormat.MEDIUM;
-        properties.setProperty(LOCAL_DATE_TIME_FORMAT_KEY, localDateTimeFormat);
-
-        localTimeFormat = JavaTemplateTemporalFormat.MEDIUM;
-        properties.setProperty(LOCAL_TIME_FORMAT_KEY, localTimeFormat);
-
-        offsetDateTimeFormat = JavaTemplateTemporalFormat.MEDIUM;
-        properties.setProperty(OFFSET_DATE_TIME_FORMAT_KEY, offsetDateTimeFormat);
-
-        offsetTimeFormat = JavaTemplateTemporalFormat.LONG;
-        properties.setProperty(OFFSET_TIME_FORMAT_KEY, offsetTimeFormat);
-
-        zonedDateTimeFormat = JavaTemplateTemporalFormat.MEDIUM;
-        properties.setProperty(ZONED_DATE_TIME_FORMAT_KEY, zonedDateTimeFormat);
-
         yearFormat = "iso";
         properties.setProperty(YEAR_FORMAT_KEY, yearFormat);
 
@@ -1225,6 +1158,25 @@ public class Configurable {
      * <p>For the possible values see {@link #setDateTimeFormat(String)}.
      *
      * <p>Defaults to {@code ""}, which is equivalent to {@code "medium"}.
+     *
+     * <p>If temporal support is enabled (see {@link Configuration#setIncompatibleImprovements(Version)} at 2.3.32, and
+     * {@link DefaultObjectWrapperBuilder#setTemporalSupport(boolean)}) this is also used for these {@link Temporal}
+     * classes: {@link LocalTime}, {@link OffsetTime}.
+     *
+     * <p>Note that to format {@link OffsetTime}-s, the format <em>should show the offset</em>, unless you
+     * are sure that the {@link #setTimeZone(TimeZone) timeZone} setting will be a time zone that never used daylight
+     * saving. This is because if the offset is not shown, FreeMarker has to convert the value to the time zone
+     * specified in the {@link #setTimeZone(TimeZone) timeZone} setting, but we don't know the day, so we can't account
+     * for daylight saving changes, and thus we can't do zone conversion reliably. To address this, you can do a few
+     * things (TODO [FREEMARKER-35] Check if these are implemented like shown):
+     * <ul>
+     *   <li>Use a format style, like {@code "medium"}, or the default {@code ""}. In this case FreeMarker will
+     *   automatically increase the veroboseness (like uses {@code "long"} instead of {@code "medium"}) until the
+     *   offset is shown. This format is also the defaults of FreeMarker, so by default you don't have to anything.
+     *   </li>
+     *   <li>Mark the offset/zone part optional in the format pattern: {@code "HH:mm[X];version=2"}.
+     *   ({@code ";version=2"} is needed for "[" and "]" to be interpreted via {@link DateTimeFormatter}.)</li>
+     * </ul>
      */
     public void setTimeFormat(String timeFormat) {
         NullArgumentException.check("timeFormat", timeFormat);
@@ -1348,11 +1300,19 @@ public class Configurable {
      *       format.
      *       
      *   <li><p>{@code "short"}, {@code "medium"}, {@code "long"}, or {@code "full"}, which that has locale-dependent
-     *       meaning defined by the Java platform (see in the documentation of {@link java.text.DateFormat}).
+     *       meaning defined by the Java platform (see in the documentation of {@link java.text.DateFormat} in case
+     *       of {@link Date}, and {@link FormatStyle} in case of {@link Temporal}-s).
      *       For date-time values, you can specify the length of the date and time part independently, be separating
      *       them with {@code _}, like {@code "short_medium"}. ({@code "medium"} means
      *       {@code "medium_medium"} for date-time values.)
-     *       
+     *       TODO [FREEMARKER-35] Check if these are implemented
+     *       Note that Java 8 has a bug (JDK-8085887) where formatting {@link LocalDateTime} and {@link LocalTime}
+     *       fails if for the given locale the format contains a time zone field. This was fixed in Java 9. To work this
+     *       issue around, for these classes, FreeMarker will decrease the verbosity if the time part (like "full" to
+     *       "long", "long" to "medium", etc.), until formatting succeeds. Also, when formatting {@link OffsetTime}
+     *       values, FreeMarker might will increase the verboseness to display the offset (see at {@link #setTimeFormat}
+     *       why).
+     *
      *   <li><p>Anything that starts with {@code "@"} followed by a letter is interpreted as a custom
      *       date/time/dateTime format, but only if either {@link Configuration#getIncompatibleImprovements()}
      *       is at least 2.3.24, or there's any custom formats defined (even if custom number format). The format of
@@ -1363,6 +1323,14 @@ public class Configurable {
      * </ul> 
      * 
      * <p>Defaults to {@code ""}, which is equivalent to {@code "medium_medium"}.
+     *
+     * <p>If temporal support is enabled (see {@link Configuration#setIncompatibleImprovements(Version)} at 2.3.32, and
+     * {@link DefaultObjectWrapperBuilder#setTemporalSupport(boolean)}) this is also used for these {@link Temporal}
+     * classes: {@link Instance}, {@link LocalDateTime}, {@link OffsetDateTime}, {@link ZonedDateTime}.
+     * For non-{@code Local} {@link Temporal}-s FreeMarker will detect if the format doesn't show the offset or zone (as
+     * is typically the case for the {@code "medium"} format), and then before formatting it will convert the value to
+     * the time zone specified in the {@link #setTimeZone(TimeZone) timeZone} setting of FreeMarker, or when parsing
+     * a string it will assume that it uses that time zone.
      */
     public void setDateTimeFormat(String dateTimeFormat) {
         NullArgumentException.check("dateTimeFormat", dateTimeFormat);
@@ -1387,264 +1355,6 @@ public class Configurable {
     }
 
     /**
-     * Sets the format used to convert {@link java.time.Instant}-s to strings, also the format that
-     * {@code someString?instant} will use to parse strings.
-     *
-     * <p>Defaults to {@code "medium"}, which means {@link FormatStyle#MEDIUM}.
-     *
-     * @param instantFormat
-     *     See the similar parameter of {@link #setZonedDateTimeFormat(String)};
-     *     {@code iso}/{@code xs} will show the time offset.
-     *
-     * @since 2.3.32
-     */
-    public void setInstantFormat(String instantFormat) {
-        this.instantFormat = instantFormat;
-    }
-
-    /**
-     * Getter pair of {@link #setInstantFormat(String)}.
-     *
-     * @since 2.3.32
-     */
-    public String getInstantFormat() {
-        return instantFormat == null ? parent.getInstantFormat() : instantFormat;
-    }
-
-    /**
-     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
-     *
-     * @since 2.3.32
-     */
-    public boolean isInstantFormatSet() {
-        return instantFormat != null;
-    }
-
-    /**
-     * Sets the format used to convert {@link java.time.LocalDate}-s to strings, also the format that
-     * {@code someString?local_date} will use to parse strings.
-     *
-     * <p>Defaults to {@code "medium"}, which means {@link FormatStyle#MEDIUM}.
-     *
-     * @param localDateFormat
-     *     See the similar parameter of {@link #setZonedDateTimeFormat(String)};
-     *     {@code iso}/{@code xs} will not show the time part.
-     *
-     * @since 2.3.32
-     */
-    public void setLocalDateFormat(String localDateFormat) {
-        this.localDateFormat = localDateFormat;
-    }
-
-    /**
-     * Getter pair of {@link #setLocalDateFormat(String)}.
-     *
-     * @since 2.3.32
-     */
-    public String getLocalDateFormat() {
-        return localDateFormat == null ? parent.getLocalDateFormat() : localDateFormat;
-    }
-
-    /**
-     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
-     *
-     * @since 2.3.32
-     */
-    public boolean isLocalDateFormatSet() {
-        return localDateFormat != null;
-    }
-
-    /**
-     * Sets the format used to convert {@link java.time.LocalDateTime}-s to strings, also the format that
-     * {@code someString?local_date_time} will use to parse strings.
-     *
-     * <p>Defaults to {@code "medium"}, which means {@link FormatStyle#MEDIUM}.
-     *
-     * @param localDateTimeFormat
-     *     See the similar parameter of {@link #setZonedDateTimeFormat(String)};
-     *     {@code iso}/{@code xs} will not show an offset.
-     *
-     * @since 2.3.32
-     */
-    public void setLocalDateTimeFormat(String localDateTimeFormat) {
-        this.localDateTimeFormat = localDateTimeFormat;
-    }
-
-    /**
-     * Getter pair of {@link #setLocalDateTimeFormat(String)}.
-     *
-     * @since 2.3.32
-     */
-    public String getLocalDateTimeFormat() {
-        return localDateTimeFormat == null ? parent.getLocalDateTimeFormat() : localDateTimeFormat;
-    }
-
-    /**
-     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
-     *
-     * @since 2.3.32
-     */
-    public boolean isLocalDateTimeFormatSet() {
-        return localDateTimeFormat != null;
-    }
-
-    /**
-     * Sets the format used to convert {@link java.time.LocalTime}-s to strings, also the format that
-     * {@code someString?local_time} will use to parse strings.
-     *
-     * <p>Defaults to {@code "medium"}, which means {@link FormatStyle#MEDIUM}.
-     *
-     * @param localTimeFormat
-     *     See the similar parameter of {@link #setZonedDateTimeFormat(String)};
-     *     {@code iso}/{@code xs} will not show the time offset.
-     *
-     * @since 2.3.32
-     */
-    public void setLocalTimeFormat(String localTimeFormat) {
-        this.localTimeFormat = localTimeFormat;
-    }
-
-    /**
-     * Getter pair of {@link #setLocalTimeFormat(String)}.
-     *
-     * @since 2.3.32
-     */
-    public String getLocalTimeFormat() {
-        return localTimeFormat == null ? parent.getLocalTimeFormat() : localTimeFormat;
-    }
-
-    /**
-     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
-     *
-     * @since 2.3.32
-     */
-    public boolean isLocalTimeFormatSet() {
-        return localTimeFormat != null;
-    }
-
-    /**
-     * Sets the format used to convert {@link java.time.OffsetDateTime}-s to strings, also the format that
-     * {@code someString?offset_date_time} will use to parse strings. FreeMarker will detect if the format doesn't
-     * show the offset (as is typically the case for the {@code "medium"} format), and then it will convert the value to
-     * the time zone specified in the {@link #setTimeZone(TimeZone) timeZone} setting of FreeMarker.
-     *
-     * <p>Defaults to {@code "medium"}, which means {@link FormatStyle#MEDIUM}, which usually doesn't show the time
-     * offset; see the parameter JavaDoc for more.
-     *
-     * @param offsetDateTimeFormat
-     *     See the similar parameter of {@link #setZonedDateTimeFormat(String)}.
-     *
-     * @since 2.3.32
-     */
-    public void setOffsetDateTimeFormat(String offsetDateTimeFormat) {
-        this.offsetDateTimeFormat = offsetDateTimeFormat;
-    }
-
-    /**
-     * Getter pair of {@link #setOffsetDateTimeFormat(String)}.
-     * @since 2.3.32
-     */
-    public String getOffsetDateTimeFormat() {
-        return offsetDateTimeFormat == null ? parent.getOffsetDateTimeFormat() : offsetDateTimeFormat;
-    }
-
-    /**
-     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
-     *
-     * @since 2.3.32
-     */
-    public boolean isOffsetDateTimeFormatSet() {
-        return offsetDateTimeFormat != null;
-    }
-
-    /**
-     * Sets the format used to convert {@link java.time.OffsetTime}-s to strings, also the format that
-     * {@code someString?offset_time} will use to parse strings. The format <b>should show the offset</b>, unless you
-     * are sure that {@link #setTimeZone(TimeZone) timeZone} setting will be a zone that has no daylight saving.
-     * This is because if the offset is not shown, FreeMarker has to convert the value to the time zone specified in the
-     * {@link #setTimeZone(TimeZone) timeZone} setting, but we don't know the day, so we can't account for daylight
-     * saving changes, and thus we can't do zone conversion reliably if a daylight saving is possible.
-     *
-     * <p>Defaults to {@code "long"}, which means {@link FormatStyle#LONG}, which usually show the time offset; see the
-     * parameter JavaDoc for more.
-     *
-     * @param offsetTimeFormat
-     *     See the similar parameter of {@link #setZonedDateTimeFormat(String)}, but it <b>must show the offset</b>
-     *     (see earlier why).
-     *
-     * @since 2.3.32
-     */
-    public void setOffsetTimeFormat(String offsetTimeFormat) {
-        this.offsetTimeFormat = offsetTimeFormat;
-    }
-
-    /**
-     * Getter pair of {@link #setOffsetTimeFormat(String)}.
-     * @since 2.3.32
-     */
-    public String getOffsetTimeFormat() {
-        return offsetTimeFormat == null ? parent.getOffsetTimeFormat() : offsetTimeFormat;
-    }
-
-    /**
-     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
-     *
-     * @since 2.3.32
-     */
-    public boolean isOffsetTimeFormatSet() {
-        return offsetTimeFormat != null;
-    }
-
-    /**
-     * Sets the format used to convert {@link java.time.ZonedDateTime}-s to strings, also the format that
-     * {@code someString?offset_date_time} will use to parse strings. FreeMarker will detect if the format doesn't
-     * show the zone or offset (as is typically the case for the {@code "medium"} format), and then it will convert the
-     * value to the time zone specified in the {@link #setTimeZone(TimeZone) timeZone} setting of FreeMarker.
-     *
-     * <p>Defaults to {@code "medium"}, which means {@link FormatStyle#MEDIUM}, which usually doesn't show the time
-     * zone; see the parameter JavaDoc for more.
-     *
-     * @param zonedDateTimeFormat
-     *     One of:
-     *     <ul>
-     *         <li>{@code "iso"}: ISO-8601 format (like {@code 2021-09-29T13:00:05.2})
-     *         <li>{@code "xs"}: XSD format (same as ISO-8601, but parsing is more restrictive)
-     *         <li>{@code "short"}, {@code "medium"}, {@code "long"}, {@code "full"}, or two of these connected with
-     *             an {@code "_"}: Refers to the {@link FormatStyle} constants. When in a pair, as in
-     *             {@code "medium_long"}, the 1st style refers to the date part, and the 2nd style to the time part.
-     *             Java doesn't specify what these styles actually mean. However, experience with Java 8 shows
-     *             that "short" and "medium" will not show the time zone or time offset (which then triggers the zone
-     *             conversion mentioned earlier), and will show months with numbers, while "long" and "full" will show
-     *             the zone and/or offset, and shows months with their names. (Also "long" and "full" before Java 9
-     *             fails for {@link LocalDateTime} and {@link LocalTime}, because of bug JDK-8085887.)
-     *          <li>Anything that starts with {@code "@"} followed by a letter is interpreted as a custom temporal
-     *              format ({@link #setCustomTemporalFormats(Map)}).
-     *     </ul>
-     *
-     * @since 2.3.32
-     */
-    public void setZonedDateTimeFormat(String zonedDateTimeFormat) {
-        this.zonedDateTimeFormat = zonedDateTimeFormat;
-    }
-
-    /**
-     * Getter pair of {@link #setZonedDateTimeFormat(String)}.
-     * @since 2.3.32
-     */
-    public String getZonedDateTimeFormat() {
-        return zonedDateTimeFormat == null ? parent.getZonedDateTimeFormat() : zonedDateTimeFormat;
-    }
-
-    /**
-     * Tells if this setting is set directly in this object or its value is coming from the {@link #getParent() parent}.
-     *
-     * @since 2.3.32
-     */
-    public boolean isZonedDateTimeFormatSet() {
-        return zonedDateTimeFormat != null;
-    }
-
-    /**
      * Sets the format used to convert {@link java.time.Year}-s to strings, also the format that
      * {@code someString?local_time} will use to parse strings.
      *
@@ -1729,26 +1439,24 @@ public class Configurable {
      */
     public String getTemporalFormat(Class<? extends Temporal> temporalClass) {
         Objects.requireNonNull(temporalClass);
-        if (temporalClass == Instant.class) {
-            return getInstantFormat();
+        // The temporal classes are final (for now at least), so we can use == operator instead of instanceof.
+        if (temporalClass == Instant.class
+                || temporalClass == LocalDateTime.class
+                || temporalClass == ZonedDateTime.class
+                || temporalClass == OffsetDateTime.class) {
+            return getDateTimeFormat();
         } else if (temporalClass == LocalDate.class) {
-            return getLocalDateFormat();
-        } else if (temporalClass == LocalDateTime.class) {
-            return getLocalDateTimeFormat();
-        } else if (temporalClass == LocalTime.class) {
-            return getLocalTimeFormat();
-        } else if (temporalClass == OffsetDateTime.class) {
-            return getOffsetDateTimeFormat();
-        } else if (temporalClass == OffsetTime.class) {
-            return getOffsetTimeFormat();
-        } else if (temporalClass == ZonedDateTime.class) {
-            return getZonedDateTimeFormat();
+            return getDateFormat();
+        } else if (temporalClass == LocalTime.class || temporalClass == OffsetTime.class) {
+            return getTimeFormat();
         } else if (temporalClass == Year.class) {
             return getYearFormat();
         } else if (temporalClass == YearMonth.class) {
             return getYearMonthFormat();
         } else {
-            Class<? extends Temporal> normTemporalClass = _CoreTemporalUtils.normalizeSupportedTemporalClass(temporalClass);
+            // Handle the unlikely situation that in some future Java version we can have subclasses.
+            Class<? extends Temporal> normTemporalClass =
+                    _CoreTemporalUtils.normalizeSupportedTemporalClass(temporalClass);
             if (normTemporalClass == temporalClass) {
                 throw new IllegalArgumentException("There's no temporal format setting for this class: "
                         + temporalClass.getName());
@@ -1792,7 +1500,13 @@ public class Configurable {
     /**
      * Associates names with formatter factories, which then can be referred by the {@link #setDateTimeFormat(String)
      * date_format}, {@link #setDateTimeFormat(String) time_format}, and {@link #setDateTimeFormat(String)
-     * datetime_format} settings with values starting with <code>@<i>name</i></code>. Beware, if you specify any custom
+     * datetime_format} settings with values starting with <code>@<i>name</i></code>.
+     *
+     * <p>It's important that the formats you set here will be only used when formatting {@link Date}-s, not when
+     * formatting {@link Temporal}-s. For the later, use {@link #setCustomTemporalFormats(Map)}. Ideally, you set the
+     * same custom formatter names with both methods.
+     *
+     * <p>Note that if you specify any custom
      * formats here, an initial {@code @} followed by a letter will have special meaning in number/date/time/datetime
      * format strings, even if {@link Configuration#getIncompatibleImprovements() incompatible_improvements} is less
      * than 2.3.24 (starting with {@link Configuration#getIncompatibleImprovements() incompatible_improvements} 2.3.24
@@ -1801,6 +1515,8 @@ public class Configurable {
      * @param customDateFormats
      *            Can't be {@code null}. The name must start with an UNICODE letter, and can only contain UNICODE
      *            letters and digits.
+     *
+     * @see #setCustomTemporalFormats(Map)
      * 
      * @since 2.3.24
      */
@@ -1871,14 +1587,19 @@ public class Configurable {
     }
 
     /**
-     * Associates names with formatter factories, which then can be referred by the various temporal format settings
-     * (like {@link #setLocalDateTimeFormat(String) local_date_time_format},
-     * {@link #setLocalDateFormat(String) local_date_format}, {@link #setLocalTimeFormat(String) local_time_format},
-     * and so on) a value starting with <code>@<i>name</i></code>.
+     * Associates names with {@link Temporal} formatter factories, which then can be referred by the
+     * {@link #setDateTimeFormat(String) date_time_format}, {@link #setDateFormat(String) date_format}, and
+     * {@link #setTimeFormat(String) time_format} settings, with values starting with <code>@<i>name</i></code>.
+     *
+     * <p>It's important that the formats you set here will be only used when formatting {@link Temporal}-s, not when
+     * formatting {@link Date}-s. For the later, use {@link #setCustomDateFormats(Map)}. Ideally, you set the same
+     * custom formatter names with both methods.
      *
      * @param customTemporalFormats
      *            Can't be {@code null}. The name must start with an UNICODE letter, and can only contain UNICODE
      *            letters and digits.
+     *            
+     * @see #setCustomDateFormats(Map) 
      *
      * @since 2.3.32
      */
@@ -3236,24 +2957,10 @@ public class Configurable {
                 setDateFormat(value);
             } else if (DATETIME_FORMAT_KEY_SNAKE_CASE.equals(name) || DATETIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
                 setDateTimeFormat(value);
-            } else if (INSTANT_FORMAT_KEY_SNAKE_CASE.equals(name) || INSTANT_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                this.instantFormat = value;
-            } else if (LOCAL_DATE_FORMAT_KEY_SNAKE_CASE.equals(name) || LOCAL_DATE_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                this.localDateFormat = value;
-            } else if (LOCAL_DATE_TIME_FORMAT_KEY_SNAKE_CASE.equals(name) || LOCAL_DATE_TIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                this.localDateTimeFormat = value;
-            } else if (LOCAL_TIME_FORMAT_KEY_SNAKE_CASE.equals(name) || LOCAL_TIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                this.localTimeFormat = value;
-            } else if (OFFSET_DATE_TIME_FORMAT_KEY_SNAKE_CASE.equals(name) || OFFSET_DATE_TIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                this.offsetDateTimeFormat = value;
-            } else if (OFFSET_TIME_FORMAT_KEY_SNAKE_CASE.equals(name) || OFFSET_TIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                this.offsetTimeFormat = value;
             } else if (YEAR_FORMAT_KEY_SNAKE_CASE.equals(name) || YEAR_FORMAT_KEY_CAMEL_CASE.equals(name)) {
                 this.yearFormat = value;
             } else if (YEAR_MONTH_FORMAT_KEY_SNAKE_CASE.equals(name) || YEAR_MONTH_FORMAT_KEY_CAMEL_CASE.equals(name)) {
                 this.yearMonthFormat = value;
-            } else if (ZONED_DATE_TIME_FORMAT_KEY_SNAKE_CASE.equals(name) || ZONED_DATE_TIME_FORMAT_KEY_CAMEL_CASE.equals(name)) {
-                this.zonedDateTimeFormat = value;
             } else if (CUSTOM_DATE_FORMATS_KEY_SNAKE_CASE.equals(name)
                     || CUSTOM_DATE_FORMATS_KEY_CAMEL_CASE.equals(name)) {
                 Map map = (Map) _ObjectBuilderSettingEvaluator.eval(
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 1208e79..5a80b2a 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -2449,10 +2449,6 @@ public final class Environment extends Configurable {
                 throw new UndefinedCustomFormatException(
                         "No custom temporal format was defined with name " + StringUtil.jQuote(name));
             }
-        } else if (formatStringLen == 0) {
-            // TODO [FREEMARKER-35] This is not right, but for now we mimic what TemporalUtils did
-            formatParams = formatString;
-            formatFactory = ToStringTemplateTemporalFormatFactory.INSTANCE;
         } else {
             formatParams = formatString;
             formatFactory = JavaTemplateTemporalFormatFactory.INSTANCE;
diff --git a/src/main/java/freemarker/core/JavaTemplateTemporalFormat.java b/src/main/java/freemarker/core/JavaTemplateTemporalFormat.java
index dbb03be..f07fbcc 100644
--- a/src/main/java/freemarker/core/JavaTemplateTemporalFormat.java
+++ b/src/main/java/freemarker/core/JavaTemplateTemporalFormat.java
@@ -61,8 +61,10 @@ class JavaTemplateTemporalFormat extends TemplateTemporalFormat {
     static final String LONG = "long";
     static final String FULL = "full";
     private static final String ANY_FORMAT_STYLE = "(" + SHORT + "|" + MEDIUM + "|" + LONG + "|" + FULL + ")";
+    // Matches format style patterns like "long_medium", "long", and "" (0-length string). It's a legacy from the
+    // pre-Temporal code that "" means "medium", and that it's the default of the date/time-related format settings.
     private static final Pattern FORMAT_STYLE_PATTERN = Pattern.compile(
-            ANY_FORMAT_STYLE + "(?:_" + ANY_FORMAT_STYLE + ")?");
+            "(?:" + ANY_FORMAT_STYLE + "(?:_" + ANY_FORMAT_STYLE + ")?)?");
 
     private final DateTimeFormatter dateTimeFormatter;
     private final ZoneId zoneId;
@@ -80,7 +82,10 @@ class JavaTemplateTemporalFormat extends TemplateTemporalFormat {
 
         DateTimeFormatter dateTimeFormatter;
         if (isFormatStyleString) {
-            FormatStyle datePartFormatStyle = FormatStyle.valueOf(formatStylePatternMatcher.group(1).toUpperCase(Locale.ROOT));
+            String group1 = formatStylePatternMatcher.group(1);
+            FormatStyle datePartFormatStyle = group1 != null
+                    ? FormatStyle.valueOf(group1.toUpperCase(Locale.ROOT))
+                    : FormatStyle.MEDIUM;
             String group2 = formatStylePatternMatcher.group(2);
             FormatStyle timePartFormatStyle = group2 != null
                     ? FormatStyle.valueOf(group2.toUpperCase(Locale.ROOT))
diff --git a/src/main/java/freemarker/core/PropertySetting.java b/src/main/java/freemarker/core/PropertySetting.java
index 2970b84..365662f 100644
--- a/src/main/java/freemarker/core/PropertySetting.java
+++ b/src/main/java/freemarker/core/PropertySetting.java
@@ -49,21 +49,9 @@ final class PropertySetting extends TemplateElement {
             Configurable.DATE_FORMAT_KEY_SNAKE_CASE,
             Configurable.DATETIME_FORMAT_KEY_CAMEL_CASE,
             Configurable.DATETIME_FORMAT_KEY_SNAKE_CASE,
-            Configurable.INSTANT_FORMAT_KEY_CAMEL_CASE,
-            Configurable.INSTANT_FORMAT_KEY_SNAKE_CASE,
-            Configurable.LOCAL_DATE_FORMAT_KEY_CAMEL_CASE,
-            Configurable.LOCAL_DATE_TIME_FORMAT_KEY_CAMEL_CASE,
-            Configurable.LOCAL_TIME_FORMAT_KEY_CAMEL_CASE,
-            Configurable.LOCAL_DATE_FORMAT_KEY_SNAKE_CASE,
-            Configurable.LOCAL_DATE_TIME_FORMAT_KEY_SNAKE_CASE,
-            Configurable.LOCAL_TIME_FORMAT_KEY_SNAKE_CASE,
             Configurable.LOCALE_KEY,
             Configurable.NUMBER_FORMAT_KEY_CAMEL_CASE,
             Configurable.NUMBER_FORMAT_KEY_SNAKE_CASE,
-            Configurable.OFFSET_DATE_TIME_FORMAT_KEY_CAMEL_CASE,
-            Configurable.OFFSET_TIME_FORMAT_KEY_CAMEL_CASE,
-            Configurable.OFFSET_DATE_TIME_FORMAT_KEY_SNAKE_CASE,
-            Configurable.OFFSET_TIME_FORMAT_KEY_SNAKE_CASE,
             Configurable.OUTPUT_ENCODING_KEY_CAMEL_CASE,
             Configurable.OUTPUT_ENCODING_KEY_SNAKE_CASE,
             Configurable.SQL_DATE_AND_TIME_TIME_ZONE_KEY_CAMEL_CASE,
@@ -77,9 +65,7 @@ final class PropertySetting extends TemplateElement {
             Configurable.YEAR_FORMAT_KEY_CAMEL_CASE,
             Configurable.YEAR_MONTH_FORMAT_KEY_CAMEL_CASE,
             Configurable.YEAR_FORMAT_KEY_SNAKE_CASE,
-            Configurable.YEAR_MONTH_FORMAT_KEY_SNAKE_CASE,
-            Configurable.ZONED_DATE_TIME_FORMAT_KEY_CAMEL_CASE,
-            Configurable.ZONED_DATE_TIME_FORMAT_KEY_SNAKE_CASE
+            Configurable.YEAR_MONTH_FORMAT_KEY_SNAKE_CASE
     };
 
 
diff --git a/src/main/java/freemarker/core/TemplateConfiguration.java b/src/main/java/freemarker/core/TemplateConfiguration.java
index 7e41d7f..f80d728 100644
--- a/src/main/java/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/freemarker/core/TemplateConfiguration.java
@@ -193,27 +193,6 @@ public final class TemplateConfiguration extends Configurable implements ParserC
         if (tc.isDateTimeFormatSet()) {
             setDateTimeFormat(tc.getDateTimeFormat());
         }
-        if (tc.isInstantFormatSet()) {
-            setInstantFormat(tc.getInstantFormat());
-        }
-        if (tc.isLocalDateFormatSet()) {
-            setLocalDateFormat(tc.getLocalDateFormat());
-        }
-        if (tc.isLocalDateTimeFormatSet()) {
-            setLocalDateTimeFormat(tc.getLocalDateTimeFormat());
-        }
-        if (tc.isLocalTimeFormatSet()) {
-            setLocalTimeFormat(tc.getLocalTimeFormat());
-        }
-        if (tc.isOffsetDateTimeFormatSet()) {
-            setOffsetDateTimeFormat(tc.getOffsetDateTimeFormat());
-        }
-        if (tc.isOffsetTimeFormatSet()) {
-            setOffsetTimeFormat(tc.getOffsetTimeFormat());
-        }
-        if (tc.isZonedDateTimeFormatSet()) {
-            setZonedDateTimeFormat(tc.getZonedDateTimeFormat());
-        }
         if (tc.isYearFormatSet()) {
             setYearFormat(tc.getYearFormat());
         }
@@ -366,27 +345,6 @@ public final class TemplateConfiguration extends Configurable implements ParserC
         if (isDateTimeFormatSet() && !template.isDateTimeFormatSet()) {
             template.setDateTimeFormat(getDateTimeFormat());
         }
-        if (isInstantFormatSet() && !template.isInstantFormatSet()) {
-            template.setInstantFormat(getInstantFormat());
-        }
-        if (isLocalDateFormatSet() && !template.isLocalDateFormatSet()) {
-            template.setLocalDateFormat(getLocalDateFormat());
-        }
-        if (isLocalTimeFormatSet() && !template.isLocalTimeFormatSet()) {
-            template.setLocalTimeFormat(getLocalTimeFormat());
-        }
-        if (isLocalDateTimeFormatSet() && !template.isLocalDateTimeFormatSet()) {
-            template.setLocalDateTimeFormat(getLocalDateTimeFormat());
-        }
-        if (isOffsetTimeFormatSet() && !template.isOffsetTimeFormatSet()) {
-            template.setOffsetTimeFormat(getOffsetTimeFormat());
-        }
-        if (isOffsetDateTimeFormatSet() && !template.isOffsetDateTimeFormatSet()) {
-            template.setOffsetDateTimeFormat(getOffsetDateTimeFormat());
-        }
-        if (isZonedDateTimeFormatSet() && !template.isZonedDateTimeFormatSet()) {
-            template.setZonedDateTimeFormat(getZonedDateTimeFormat());
-        }
         if (isYearFormatSet() && !template.isYearFormatSet()) {
             template.setYearFormat(getYearFormat());
         }
@@ -741,13 +699,6 @@ public final class TemplateConfiguration extends Configurable implements ParserC
                 || isCustomNumberFormatsSet()
                 || isDateFormatSet()
                 || isDateTimeFormatSet()
-                || isInstantFormatSet()
-                || isLocalDateFormatSet()
-                || isLocalTimeFormatSet()
-                || isLocalDateTimeFormatSet()
-                || isOffsetTimeFormatSet()
-                || isOffsetDateTimeFormatSet()
-                || isZonedDateTimeFormatSet()
                 || isYearFormatSet()
                 || isYearMonthFormatSet()
                 || isLazyImportsSet()
diff --git a/src/main/java/freemarker/core/_CoreTemporalUtils.java b/src/main/java/freemarker/core/_CoreTemporalUtils.java
index f95906c..ca1032b 100644
--- a/src/main/java/freemarker/core/_CoreTemporalUtils.java
+++ b/src/main/java/freemarker/core/_CoreTemporalUtils.java
@@ -28,12 +28,10 @@ import java.time.OffsetDateTime;
 import java.time.OffsetTime;
 import java.time.Year;
 import java.time.YearMonth;
-import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.temporal.Temporal;
 import java.util.Arrays;
 import java.util.List;
-import java.util.stream.Stream;
 
 import freemarker.template.Configuration;
 
@@ -105,20 +103,15 @@ public class _CoreTemporalUtils {
      */
     public static String temporalClassToFormatSettingName(Class<? extends Temporal> temporalClass) {
         temporalClass = normalizeSupportedTemporalClass(temporalClass);
-        if (temporalClass == Instant.class) {
-            return Configuration.INSTANT_FORMAT_KEY;
+        if (temporalClass == Instant.class
+                || temporalClass == LocalDateTime.class
+                || temporalClass == ZonedDateTime.class
+                || temporalClass == OffsetDateTime.class) {
+            return Configuration.DATETIME_FORMAT_KEY;
         } else if (temporalClass == LocalDate.class) {
-            return Configuration.LOCAL_DATE_FORMAT_KEY;
-        } else if (temporalClass == LocalDateTime.class) {
-            return Configuration.LOCAL_DATE_TIME_FORMAT_KEY;
-        } else if (temporalClass == LocalTime.class) {
-            return Configuration.LOCAL_TIME_FORMAT_KEY;
-        } else if (temporalClass == OffsetDateTime.class) {
-            return Configuration.OFFSET_DATE_TIME_FORMAT_KEY;
-        } else if (temporalClass == OffsetTime.class) {
-            return Configuration.OFFSET_TIME_FORMAT_KEY;
-        } else if (temporalClass == ZonedDateTime.class) {
-            return Configuration.ZONED_DATE_TIME_FORMAT_KEY;
+            return Configuration.DATE_FORMAT_KEY;
+        } else if (temporalClass == LocalTime.class || temporalClass == OffsetTime.class) {
+            return Configuration.TIME_FORMAT_KEY;
         } else if (temporalClass == YearMonth.class) {
             return Configuration.YEAR_MONTH_FORMAT_KEY;
         } else if (temporalClass == Year.class) {
@@ -127,5 +120,5 @@ public class _CoreTemporalUtils {
             throw new IllegalArgumentException("Unsupported temporal class: " + temporalClass.getName());
         }
     }
-    
+
 }
diff --git a/src/test/java/freemarker/core/CoercionToTextualTest.java b/src/test/java/freemarker/core/CoercionToTextualTest.java
index efa015a..1f121a8 100644
--- a/src/test/java/freemarker/core/CoercionToTextualTest.java
+++ b/src/test/java/freemarker/core/CoercionToTextualTest.java
@@ -138,7 +138,6 @@ public class CoercionToTextualTest extends TemplateTest {
         cfg.setCustomTemporalFormats(Collections.singletonMap("HI", HTMLISOTemplateTemporalFormatFactory.INSTANCE));
         cfg.setNumberFormat("@G 3");
         cfg.setDateTimeFormat("@HI");
-        cfg.setInstantFormat("@HI");
         cfg.setBooleanFormat("y,n");
         cfg.setTimeZone(DateUtil.UTC);
 
diff --git a/src/test/java/freemarker/core/CoreTemporalUtilTest.java b/src/test/java/freemarker/core/CoreTemporalUtilTest.java
index 2eab1f5..36fd589 100644
--- a/src/test/java/freemarker/core/CoreTemporalUtilTest.java
+++ b/src/test/java/freemarker/core/CoreTemporalUtilTest.java
@@ -19,6 +19,7 @@
 
 package freemarker.core;
 
+import static org.hamcrest.Matchers.*;
 import static org.junit.Assert.*;
 
 import java.time.chrono.ChronoLocalDate;
@@ -62,8 +63,9 @@ public class CoreTemporalUtilTest {
 
         Set<String> uniqueSettingNames = new HashSet<>();
         for (Class<? extends Temporal> supportedTemporalClass : _CoreTemporalUtils.SUPPORTED_TEMPORAL_CLASSES) {
-            assertTrue(uniqueSettingNames.add(_CoreTemporalUtils.temporalClassToFormatSettingName(supportedTemporalClass)));
+            uniqueSettingNames.add(_CoreTemporalUtils.temporalClassToFormatSettingName(supportedTemporalClass));
         }
+        assertThat(uniqueSettingNames.size(), equalTo(_CoreTemporalUtils.SUPPORTED_TEMPORAL_CLASSES.size() - 4));
         assertTrue(uniqueSettingNames.stream().allMatch(it -> cfg.getSettingNames(false).contains(it)));
 
         try {
diff --git a/src/test/java/freemarker/core/TemporalErrorMessagesTest.java b/src/test/java/freemarker/core/TemporalErrorMessagesTest.java
index 1448d25..201062d 100644
--- a/src/test/java/freemarker/core/TemporalErrorMessagesTest.java
+++ b/src/test/java/freemarker/core/TemporalErrorMessagesTest.java
@@ -20,6 +20,7 @@
 package freemarker.core;
 
 import java.time.LocalTime;
+import java.time.YearMonth;
 
 import org.junit.Test;
 
@@ -42,19 +43,19 @@ public class TemporalErrorMessagesTest extends TemplateTest {
 
     @Test
     public void testDefaultFormatStringBadFormatString() throws TemplateException {
-        getConfiguration().setSetting("local_time_format", "ABCDEF");
-        addToDataModel("t", LocalTime.now());
-        assertErrorContains("${t}", "local_time_format", "ABCDEF");
-        assertErrorContains("${t?string}", "local_time_format", "ABCDEF");
+        getConfiguration().setSetting("year_month_format", "ABCDEF");
+        addToDataModel("t", YearMonth.now());
+        assertErrorContains("${t}", "year_month", "ABCDEF");
+        assertErrorContains("${t?string}", "year_month", "ABCDEF");
     }
 
     @Test
     public void testDefaultFormatStringIncompatibleFormatString() throws TemplateException {
-        getConfiguration().setSetting("local_time_format", "yyyy-HH");
-        addToDataModel("t", LocalTime.now());
+        getConfiguration().setSetting("year_month_format", "yyyy-mm"); // Deliberately wrong: "mm" is minutes
+        addToDataModel("t", YearMonth.now());
         // TODO [FREEMARKER-35] Should contain "local_time_format" too
-        assertErrorContains("${t}", "Failed to format temporal value", "yyyy-HH", "YearOfEra");
-        assertErrorContains("${t?string}", "Failed to format temporal value", "yyyy-HH", "YearOfEra");
+        assertErrorContains("${t}", "Failed to format temporal value", "yyyy-mm", "MinuteOfHour");
+        assertErrorContains("${t?string}", "Failed to format temporal value", "yyyy-mm", "MinuteOfHour");
     }
 
 }
diff --git a/src/test/java/freemarker/core/TemporalFormatTest.java b/src/test/java/freemarker/core/TemporalFormatTest.java
index 3e0e3ed..83268e0 100644
--- a/src/test/java/freemarker/core/TemporalFormatTest.java
+++ b/src/test/java/freemarker/core/TemporalFormatTest.java
@@ -62,7 +62,7 @@ public class TemporalFormatTest {
                 "11:00",
                 formatTemporal(
                         conf -> {
-                            conf.setOffsetTimeFormat("HH:mm");
+                            conf.setTimeFormat("HH:mm");
                             conf.setTimeZone(zoneWithoutDST);
                         },
                         offsetTime));
@@ -72,7 +72,7 @@ public class TemporalFormatTest {
                     "11:00",
                     formatTemporal(
                             conf -> {
-                                conf.setOffsetTimeFormat("HH:mm");
+                                conf.setTimeFormat("HH:mm");
                                 conf.setTimeZone(zoneWithDST);
                             },
                             offsetTime));
@@ -85,7 +85,7 @@ public class TemporalFormatTest {
                 "10:00+01",
                 formatTemporal(
                         conf -> {
-                            conf.setOffsetTimeFormat("HH:mmX");
+                            conf.setTimeFormat("HH:mmX");
                             conf.setTimeZone(zoneWithDST);
                         },
                         offsetTime));
@@ -94,7 +94,7 @@ public class TemporalFormatTest {
                 "10:00+01",
                 formatTemporal(
                         conf -> {
-                            conf.setOffsetTimeFormat("HH:mmX");
+                            conf.setTimeFormat("HH:mmX");
                             conf.setTimeZone(zoneWithoutDST);
                         },
                         offsetTime));
@@ -128,9 +128,7 @@ public class TemporalFormatTest {
                         + "2021-12-30 10:30, 2021-12-30 08:30, 2021-12-30 15:30",
                 formatTemporal(
                         conf -> {
-                            conf.setLocalDateTimeFormat("yyyy-MM-dd HH:mm");
-                            conf.setOffsetDateTimeFormat("yyyy-MM-dd HH:mm");
-                            conf.setZonedDateTimeFormat("yyyy-MM-dd HH:mm");
+                            conf.setDateTimeFormat("yyyy-MM-dd HH:mm");
                             conf.setTimeZone(gbZone);
                         },
                         summerLocalDateTime, summerOffsetDateTime, summerZonedDateTime,
@@ -140,9 +138,7 @@ public class TemporalFormatTest {
                         + "2021-12-30 10:30, 2021-12-30 08:30, 2021-12-30 15:30",
                 formatTemporal(
                         conf -> {
-                            conf.setLocalDateTimeFormat("yyyy-MM-dd HH:mm");
-                            conf.setOffsetDateTimeFormat("yyyy-MM-dd HH:mm");
-                            conf.setZonedDateTimeFormat("yyyy-MM-dd HH:mm");
+                            conf.setDateTimeFormat("yyyy-MM-dd HH:mm");
                             conf.setTimeZone(DateUtil.UTC);
                         },
                         summerLocalDateTime, summerOffsetDateTime, summerZonedDateTime,
@@ -154,8 +150,7 @@ public class TemporalFormatTest {
                         + "2021-12-30 10:30+02, 2021-12-30 10:30-05",
                 formatTemporal(
                         conf -> {
-                            conf.setOffsetDateTimeFormat("yyyy-MM-dd HH:mmX");
-                            conf.setZonedDateTimeFormat("yyyy-MM-dd HH:mmX");
+                            conf.setDateTimeFormat("yyyy-MM-dd HH:mmX");
                             conf.setTimeZone(gbZone);
                         },
                         summerOffsetDateTime, summerZonedDateTime,
@@ -167,7 +162,7 @@ public class TemporalFormatTest {
         try {
             formatTemporal(
                     conf -> {
-                        conf.setLocalDateTimeFormat("yyyy-MM-dd HH:mmX");
+                        conf.setDateTimeFormat("yyyy-MM-dd HH:mmX");
                     },
                     LocalDateTime.of(2021, 10, 30, 1, 2));
             fail();
diff --git a/src/test/java/freemarker/core/TemporalFormatTest2.java b/src/test/java/freemarker/core/TemporalFormatTest2.java
index c519c68..1329579 100644
--- a/src/test/java/freemarker/core/TemporalFormatTest2.java
+++ b/src/test/java/freemarker/core/TemporalFormatTest2.java
@@ -61,12 +61,12 @@ public class TemporalFormatTest2 extends TemplateTest {
                 "${d?string.@epoch} ${d?string.@epoch} <#setting locale='de_DE'>${d?string.@epoch}",
                 "123456789 123456789 123456789");
 
-        getConfiguration().setOffsetDateTimeFormat("@epoch");
+        getConfiguration().setDateTimeFormat("@epoch");
         assertOutput(
                 "${d} ${d?string} <#setting locale='de_DE'>${d}",
                 "123456789 123456789 123456789");
 
-        getConfiguration().setOffsetDateTimeFormat("@htmlIso");
+        getConfiguration().setDateTimeFormat("@htmlIso");
         assertOutput(
                 "${d} ${d?string} <#setting locale='de_DE'>${d}",
                 "1970-01-02<span class='T'>T</span>10:17:36.789Z "
diff --git a/src/test/resources/freemarker/test/templatesuite/templates/temporal.ftl b/src/test/resources/freemarker/test/templatesuite/templates/temporal.ftl
index cdadba8..db30dcf 100644
--- a/src/test/resources/freemarker/test/templatesuite/templates/temporal.ftl
+++ b/src/test/resources/freemarker/test/templatesuite/templates/temporal.ftl
@@ -16,6 +16,7 @@
   specific language governing permissions and limitations
   under the License.
 -->
+<@assertEquals expected="Apr 5, 2003 7:07:08 AM" actual=dateTime?string />
 <@assertEquals expected="Apr 5, 2003 7:07:08 AM" actual=instant?string />
 <@assertEquals expected="Apr 5, 2003 6:07:08 AM" actual=localDateTime?string />
 <@assertEquals expected="Apr 5, 2003" actual=localDate?string />
@@ -117,19 +118,19 @@
 
 
 <#setting locale="en_US">
-<#setting instantFormat="yyyy MMM dd HH:mm:ss">
+<#setting datetimeFormat="yyyy MMM dd HH:mm:ss">
 <@assertEquals expected="2003 Apr 05 01:07:08" actual=instant?string />
-<#setting localDateTimeFormat="yyyy MMM dd HH:mm:ss">
+<#setting datetimeFormat="yyyy MMM dd HH:mm:ss">
 <@assertEquals expected="2003 Apr 05 06:07:08" actual=localDateTime?string />
-<#setting localDateFormat="yyyy MMM dd">
+<#setting dateFormat="yyyy MMM dd">
 <@assertEquals expected="2003 Apr 05" actual=localDate?string />
-<#setting localDateTimeFormat="HH:mm:ss">
+<#setting datetimeFormat="HH:mm:ss">
 <@assertEquals expected="6:07:08 AM" actual=localTime?string />
-<#setting offsetDateTimeFormat="yyyy MMM dd HH:mm:ss">
+<#setting datetimeFormat="yyyy MMM dd HH:mm:ss">
 <@assertEquals expected="2003 Apr 05 01:07:08" actual=offsetDateTime?string />
 <#setting yearFormat="yyyy">
 <@assertEquals expected="2003" actual=year?string />
 <#setting yearMonthFormat="yyyy MMM">
 <@assertEquals expected="2003 Apr" actual=yearMonth?string />
-<#setting zonedDateTimeFormat="yyyy MMM dd HH:mm:ss">
+<#setting datetimeFormat="yyyy MMM dd HH:mm:ss">
 <@assertEquals expected="2003 Apr 05 01:07:08" actual=zonedDateTime?string />