You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@freemarker.apache.org by Daniel Dekany <da...@gmail.com> on 2022/02/17 08:40:06 UTC

Re: java.time.LocalDate support for Freemarker

Just to keep us updated... This wasn't abandoned, but dragging. Part of the
reason is that I keep discovering complications that need to be addressed.
But it will be done, and when it's done, that will be released as soon as
possible of course.

On Mon, Dec 27, 2021 at 10:47 PM Daniel Dekany <da...@gmail.com>
wrote:

> Now the "translating SimpleDateFormat pattern syntax to DateTimeFormatter
> pattern syntax" part is done. Actually it parses the pattern, and builds a
> DateTimeFormatter from it directly (so there's no translated pattern). It
> seems to work well enough (after quite a few corner cases were addressed),
> which is a relieft, as this was crucial for using common format settings
> among Date-s and java.time Temporal-s.
>
> Will continue with the fancier extended aka. "version 2" format. See
> question about its syntax in previous mail, if you want to influence how
> it will be.
>
> On Mon, Dec 20, 2021 at 2:12 PM Daniel Dekany <da...@gmail.com>
> wrote:
>
>> What's in FREEMARKER-35, for a few days now, already uses date_format,
>> time_format and datetime_format for the java.time values as well, and the
>> related new settings were removed. But translating the SimpleDateFormat
>> pattern syntax to DateTimeFormatter pattern syntax is not done yet, so for
>> now these unified settings only work well if the pattern means the same for
>> both formatter classes. (For the most common patterns that happens to be
>> the case, but, obviously I will have to parse the pattern and generate a
>> new one from it.)
>>
>> Also, the pattern syntax is not yet extended, so you can't indicate that
>> it uses  DateTimeFormatter syntax. Thus java.util.Date formatting always
>> uses a SimpleDateFormat for now.
>>
>> So how exactly the extended syntax should look? I would start from the
>> "extended Java decimal format" that FreeMarker already uses for a good
>> while, like "0.#;;roundingMode=halfEven" (see
>> https://freemarker.apache.org/docs/ref_builtins_number.html#ref_builtin_string_for_number).
>> Except now a single ";" will be enough, as ";" is not already used, unlike
>> with DecimalFormat. Then we could have the following key-value pairs:
>>
>>    - version:
>>       - "1": SimpleDateFormat syntax, which is also the default
>>       - "2": for  DateTimeFormatter syntax + FreeMarker
>>       extensions (which makes semicolon reserved). Example: 'HH:mm[X];version=2'
>>    - for${Type}, like forLocalTime: Specify a different pattern if the
>>    value class is this
>>
>> Good news is, these can be added without breaking backward compatibility,
>> and without extra setting to enable the extended syntax, because the letter
>> "v" in "version", and "f" in "for${Type}" (and some more letters) are
>> invalid pattern characters for SimpleDateFormat.
>>
>> I wonder if ";version=2" is good. While something like
>> ";javaDotTimePatternSyntax=true" is more self explanatory, it's also
>> comically verbose. So, I'm afraid people will have to search for the
>> meaning with any sane syntax we can come up with. But if they have to
>> anway, what if we go wilder, and say that the new syntax is indicated with
>> an initial "v2:", as in "v2:HH:mm[X]". It's less verbose. Also, it avoids
>> the somewhat confusing behavior that wherever you put ";version=2", it
>> applies to the whole pattern. WDYT? Any other ideas?
>>
>> Different...  FREEMARKER-35 now also handles adjusting the Java format
>> time styles (short, medium, long, full) for LocalDateTime, LocalTime, and
>> OffsetTime. Before that, you often ended up with runtime error, either
>> because the style wanted to show the zone that's not available in local
>> temporal, or because the style did not show the offset that is often to
>> display an OffsetTime if DST is a possibility. Earlier I said that I add
>> settings to set the upper and lower bounds of the time style for these
>> types. Instead, I made this adjustment entirely dynamic and automatic, and
>> there are no settings to worry about. I realized it has to be like that,
>> because what the proper closest usable time style depends on the locale, or
>> even Java version and local Java customizations.
>>
>>
>> On Mon, Dec 13, 2021 at 1:01 PM Geoffrey De Smet <ge...@gmail.com>
>> wrote:
>>
>>> Good point, Daniel
>>>
>>> I agree on the need for the mixed situation support.
>>>
>>> About the same pattern, I also agree losing simplicity is not worth it
>>> and BC is needed for datetime_format, date_format, and time_format.
>>> Having access to LocalDate etc will be well worth that wrinkle.
>>>
>>> With kind regards,
>>> Geoffrey De Smet
>>> On 13/12/2021 12:27, Daniel Dekany wrote:
>>>
>>> In many (certainly in most) projects it's not a realistic
>>> expectation that they completely replace java.util.Date-s with Temporal-s
>>> at once. Even if you think you have done it, it would be difficult to
>>> guarantee that no java.util.Date will find its way into the data-model
>>> sometimes later, maybe coming from some library you don't control. So
>>> FreeMarker must be able to cope with the mixed situation.
>>>
>>> Regarding using the same pattern syntax in Java code and templates, we
>>> got a backward compatibility constraint here. Though, in principle there
>>> could be a setting to change the default syntax to "new", and then to use
>>> SimpleDateFormat syntax one had to use ";syntax=old" in the pattern. But
>>> the problem with that is then you have to know the FreeMarker configuration
>>> to use a pattern without explicit ";syntax=", while earlier you had a piece
>>> of mind if you don't use new features (like "[" and "]"), as then a pattern
>>> with SimpleDateFormat syntax will always work. I think people will rarely
>>> need DateTimeFromatter-exclusive features, so losing that simplicity is not
>>> worth it.
>>>
>>> On Mon, Dec 13, 2021 at 10:59 AM Geoffrey De Smet <
>>> ge0ffrey.spam@gmail.com> wrote:
>>>
>>>>
>>>> On 13/12/2021 09:15, Daniel Dekany wrote:
>>>>
>>>> There was progress made in that branch like one month ago. More is
>>>> needed, and hopefully will be done this month.
>>>>
>>>> Now, there are a few dilemmas with this feature branch (FREEMARKER-35).
>>>> Here's one of them.
>>>>
>>>> For a long time we have the datetime_format, date_format, and
>>>> time_format settings for java.util.Date-s. In the original contribution
>>>> (the PR), new format settings were added for each supported temporal type:
>>>> local_date_time_format, offset_date_time_format, zoned_date_time_format,
>>>> local_date_time_format, offset_date_time_format, zoned_date_time_format, instant_format,
>>>> local_date_format, local_time_format, and offset_time_format (and
>>>> year_format, and year_month_format). These can have similar values like the
>>>> old format settings (except that patterns are interpreted with
>>>> DateTimeFromatter instead of with SimpleDateFormat). This is the obvious
>>>> approach from the perspective of the template engine developer, but I think
>>>> it's not practical for the users. Certainly, you just want to say that the
>>>> datetime_format is like "yyyy.MM.dd" (or is "iso", etc.), and then want all
>>>> kinds of date-time objects formatted like that. So you don't want to
>>>> consider if it's a java.util.Date, or a LocalDateTime, or an
>>>> OffsetDateTime, or a ZonedDateTime, or an Instant. Most of the time at
>>>> least, you don't want to present them differently. There I intend to remove
>>>> all these new settings, except year_format, and year_month_format.
>>>> Everything else will be governed by just datetime_format, date_format, and
>>>> time_format.
>>>>
>>>> What do you guys think?
>>>>
>>>> +1 (non-contributor)
>>>> Regardless of the Data/LocalDate technology, a user wants to set only
>>>> one default date format for their files.
>>>>
>>>> In the very rare cases that that is not the case, they can overwrite
>>>> the default explicitly by passing the format explicitly in the ftl snippet
>>>> that adds the date.
>>>> The technology type (Date vs LocalDate) will and should not help to
>>>> differentiate such cases.
>>>>
>>>>
>>>> Now, there will be quite much magic going on with that:
>>>>
>>>>    - Dealing with formats that doesn't show offset or zone.  These
>>>>    tricks are already done with the new settings too, but it's even more
>>>>    important if you have a single shared format string:
>>>>       - If you format an OffsetDateTime or ZonedDateTime, and the
>>>>       format doesn't show the offset or time zone, it's converted to the time
>>>>       zone specified in the time_zone setting of FreeMarker.
>>>>       - Formatting OffsetTime-s will fail if the format doesn't show
>>>>       the offset, and time_zone has DST. (Currently that throws this:
>>>>       freemarker.core.InvalidFormatParametersException: The format must show the
>>>>       time offset, as the current FreeMarker time zone, "Europe/Budapest", may
>>>>       uses Daylight Saving Time, and thus it's not possible to convert the value
>>>>       to the local time in that zone, since we don't know the day.)
>>>>    - The pattern syntax used for datetime_format, date_format, and
>>>>    time_format will have to be extended (currently it simply uses
>>>>    SimpleDateFormat to parse it):
>>>>       - To optionally use DateTimeFormatter syntax. For example:
>>>>       "HH/mm/ss[X];syntax=new". ("[" and "]" are output literally with the old
>>>>       syntax, but with ";syntax=new" they indicate an optional section.) With
>>>>       ";syntax=new", even java.util.Date-s will be formatted
>>>>       with DateTimeFormatter.
>>>>       - To automatically translate SimpleDateFormat syntax to
>>>>       DateTimeFormatter behind the scenes, when we have no ";syntax=new". This
>>>>       will be done only if a Temporal has to be formatted, while java.util.Date-s
>>>>       will be still formatted with SimpleDateFormat, to ensure 100% backward
>>>>       compatibility.
>>>>       - To allow overriding the pattern for a specific type. For
>>>>       example "yyyy-MM-dd HH:mm;instant=yyyy-MM-dd HH:mm:ss.S"
>>>>       - Of course, the ";name=value" extension will be disabled by
>>>>       default (we need a setting for that, like
>>>>       temporal_format_extensions=true/false), if incompatible_improvements is set
>>>>       to <= 2.3.32
>>>>    - Setting values like "short", "medium", "long", and "full" (i.e.,
>>>>    Java format styles) doesn't work well with Temporal-s, so having a shared
>>>>    format setting becomes quite useless if you want to use these values,
>>>>    unless I will pull some dirty tricks (which I intend to do of course).
>>>>    There are two problems to counter. On Java 8 (but not on Java 9+), "long"
>>>>    or higher will fail with temporals that have no offset or zone, as they
>>>>    mistakenly didn't mark the zone/offset fields in the format patterns as
>>>>    optional (at least for the locales I tried). Also, formatting OffsetTime
>>>>    with "medium" or less will generally fail because of the DST issue I
>>>>    described earlier in this mail (i.e., the format must show the offset). So,
>>>>    I think, I will add two new settings: offset_time_style_lower_bound with
>>>>    default "long", and local_temporal_style_upper_bound with default "medium".
>>>>    With an example, if a LocalDateTime is formatted, and the datetime_format
>>>>    is "long", but  local_temporal_style_upper_bound is "medium", then because
>>>>    "long" is greater than "medium", we will ignore it and just format with
>>>>    "medium" style. Yeah, it's potentially quite confusing, but what better can
>>>>    I do? Without these two style boundary settings, and extended format
>>>>    strings being enabled, you could use this as datetime_format:
>>>>    "full;localDateTime=medium". But I think in reality people will just
>>>>    naively(?) use datetime_format="full", and time_format="medium", and then
>>>>    burnt by it on runtime (maybe only in production).
>>>>    - Who knows what else will come up... like when I add support for
>>>>    parsing, which wasn't done yet. But if you agree that using the 3 old
>>>>    format settings for everything is crucial, somehow I will have to get over
>>>>    them.
>>>>
>>>> The more you can leave these decisions inline with the javax.time
>>>> standards, the better.
>>>>
>>>> Motivation: In our team project, I want the LocalDate etc to behave
>>>> like they do in java code.
>>>> (I even want to ban the use of java.util.Date in our ftl's because
>>>> java.util.date is error prone.)
>>>> Worst case scenario,
>>>> maybe make a simple boolean config switch:
>>>> freemarker.dateTech=JAVA_UTIL_DATE xor JAVA_TIME
>>>> to enforce the ftl's to not mix Date and LocalDate
>>>> while using the same settings (datetime_format, date_format, and
>>>> time_format)
>>>> but allow the behavior to differ (JUD uses the backward compatible
>>>> behavior, java.time follows the java.time approach which follows ISO
>>>> standards).
>>>>
>>>> Wdyt?
>>>>
>>>> With kind regards,
>>>> Geoffrey De Smet
>>>>
>>>>
>>>>
>>>> On Thu, Dec 9, 2021 at 9:20 AM Geoffrey De Smet <
>>>> ge0ffrey.spam@gmail.com> wrote:
>>>>
>>>>> Hi,
>>>>>
>>>>> This feature would really modernize Freemarker for us.
>>>>>
>>>>> Is there any news on LocalDate support for Freemarker?
>>>>> Anything we can do to speed things along?
>>>>>
>>>>> With kind regards,
>>>>> Geoffrey De Smet
>>>>>
>>>>> On 02/10/2021 20:24, Daniel Dekany wrote:
>>>>> > Hi,
>>>>> >
>>>>> > Not yet, but there's a FREEMARKER-35 branch that deals with all the
>>>>> > java.time types. It works at the first sight, but actually will need
>>>>> a
>>>>> > significant amount of work before it can be released. I plan to put
>>>>> > aside time for a "sprint" on it near the end of October. We will see.
>>>>> > And yes, I also want to add at least a few date operations built-ins.
>>>>> >
>>>>> > On Fri, Oct 1, 2021 at 9:59 AM Geoffrey De Smet <
>>>>> ge0ffrey.spam@gmail.com> wrote:
>>>>> >> Hi all,
>>>>> >>
>>>>> >> Does Freemarker have plans to support using java.time.LocalDate
>>>>> instead
>>>>> >> of java.util.Date?
>>>>> >>
>>>>> >> The latter is causing off-by-one errors for in our Freemarker
>>>>> templates
>>>>> >> if executed in certain timezones (and adjusting the timezone opens
>>>>> >> another can of worms).
>>>>> >> See https://github.com/jbake-org/jbake/issues/726
>>>>> >>
>>>>> >> Also, many java.time methods, such as plusDays(3) or next monday,
>>>>> >> would be very welcome in Freemarker templates.
>>>>> >>
>>>>> >> --
>>>>> >>
>>>>> >> With kind regards,
>>>>> >> Geoffrey De Smet
>>>>> >>
>>>>> >
>>>>>
>>>>
>>>>
>>>> --
>>>> Best regards,
>>>> Daniel Dekany
>>>>
>>>>
>>>
>>> --
>>> Best regards,
>>> Daniel Dekany
>>>
>>>
>>
>> --
>> Best regards,
>> Daniel Dekany
>>
>
>
> --
> Best regards,
> Daniel Dekany
>


-- 
Best regards,
Daniel Dekany

Re: java.time.LocalDate support for Freemarker

Posted by Denis Bredelet <br...@me.com.INVALID>.
Hi Daniel,

> Le 17 févr. 2022 à 08:40, Daniel Dekany <da...@gmail.com> a écrit :
> 
> Just to keep us updated... This wasn't abandoned, but dragging. Part of the
> reason is that I keep discovering complications that need to be addressed.
> But it will be done, and when it's done, that will be released as soon as
> possible of course.

That sounds great!

More comments below.
> On Mon, Dec 27, 2021 at 10:47 PM Daniel Dekany <da...@gmail.com>
> wrote:
> 
>> Now the "translating SimpleDateFormat pattern syntax to DateTimeFormatter
>> pattern syntax" part is done. Actually it parses the pattern, and builds a
>> DateTimeFormatter from it directly (so there's no translated pattern). It
>> seems to work well enough (after quite a few corner cases were addressed),
>> which is a relieft, as this was crucial for using common format settings
>> among Date-s and java.time Temporal-s.
>> 
>> Will continue with the fancier extended aka. "version 2" format. See
>> question about its syntax in previous mail, if you want to influence how
>> it will be.
>>> … ...
>>>   - version:
>>>      - "1": SimpleDateFormat syntax, which is also the default
>>>      - "2": for  DateTimeFormatter syntax + FreeMarker
>>>      extensions (which makes semicolon reserved). Example: 'HH:mm[X];version=2'
>>>   - for${Type}, like forLocalTime: Specify a different pattern if the
>>>   value class is this
>>> 
>>> Good news is, these can be added without breaking backward compatibility,
>>> and without extra setting to enable the extended syntax, because the letter
>>> "v" in "version", and "f" in "for${Type}" (and some more letters) are
>>> invalid pattern characters for SimpleDateFormat.
>>> 
>>> I wonder if ";version=2" is good. While something like
>>> ";javaDotTimePatternSyntax=true" is more self explanatory, it's also
>>> comically verbose. So, I'm afraid people will have to search for the
>>> meaning with any sane syntax we can come up with. But if they have to
>>> anway, what if we go wilder, and say that the new syntax is indicated with
>>> an initial "v2:", as in "v2:HH:mm[X]". It's less verbose. Also, it avoids
>>> the somewhat confusing behavior that wherever you put ";version=2", it
>>> applies to the whole pattern. WDYT? Any other ideas?

I am OK with that idea.

>>> Different...  FREEMARKER-35 now also handles adjusting the Java format
>>> time styles (short, medium, long, full) for LocalDateTime, LocalTime, and
>>> OffsetTime. Before that, you often ended up with runtime error, either
>>> because the style wanted to show the zone that's not available in local
>>> temporal, or because the style did not show the offset that is often to
>>> display an OffsetTime if DST is a possibility. Earlier I said that I add
>>> settings to set the upper and lower bounds of the time style for these
>>> types. Instead, I made this adjustment entirely dynamic and automatic, and
>>> there are no settings to worry about. I realized it has to be like that,
>>> because what the proper closest usable time style depends on the locale, or
>>> even Java version and local Java customizations.
>>> 
>>> 
>>> On Mon, Dec 13, 2021 at 1:01 PM Geoffrey De Smet <ge...@gmail.com>
>>> wrote:
>>> 
>>>> Good point, Daniel
>>>> 
>>>> I agree on the need for the mixed situation support.
>>>> 
>>>> About the same pattern, I also agree losing simplicity is not worth it
>>>> and BC is needed for datetime_format, date_format, and time_format.
>>>> Having access to LocalDate etc will be well worth that wrinkle.

Yes

>>>> With kind regards,
>>>> Geoffrey De Smet
>>>> On 13/12/2021 12:27, Daniel Dekany wrote:
>>>> … ...
>>>>>  So you don’t want to
>>>>> consider if it's a java.util.Date, or a LocalDateTime, or an
>>>>> OffsetDateTime, or a ZonedDateTime, or an Instant. Most of the time at
>>>>> least, you don't want to present them differently. There I intend to remove
>>>>> all these new settings, except year_format, and year_month_format.
>>>>> Everything else will be governed by just datetime_format, date_format, and
>>>>> time_format.
>>>>> 
>>>>> What do you guys think?
>>>>> 
>>>>> +1 (non-contributor)

Yes

— Denis.