freemarker-java8

This is a tiny Java library that adds basic format support for the new Java 8 date/time api in FreeMarker. Based on the freemarker-java8 library published by Amedia Utvikling AS.

License

License

Categories

Categories

Java 8 Languages
GroupId

GroupId

com.munich-airport.freemarker
ArtifactId

ArtifactId

freemarker-java8
Last Version

Last Version

2.0.0
Release Date

Release Date

Type

Type

jar
Description

Description

freemarker-java8
This is a tiny Java library that adds basic format support for the new Java 8 date/time api in FreeMarker. Based on the freemarker-java8 library published by Amedia Utvikling AS.
Project URL

Project URL

https://github.com/Munich-Airport/freemarker-java-8
Project Organization

Project Organization

Flughafen München GmbH
Source Code Management

Source Code Management

https://github.com/Munich-Airport/freemarker-java-8

Download freemarker-java8

How to add to project

<!-- https://jarcasting.com/artifacts/com.munich-airport.freemarker/freemarker-java8/ -->
<dependency>
    <groupId>com.munich-airport.freemarker</groupId>
    <artifactId>freemarker-java8</artifactId>
    <version>2.0.0</version>
</dependency>
// https://jarcasting.com/artifacts/com.munich-airport.freemarker/freemarker-java8/
implementation 'com.munich-airport.freemarker:freemarker-java8:2.0.0'
// https://jarcasting.com/artifacts/com.munich-airport.freemarker/freemarker-java8/
implementation ("com.munich-airport.freemarker:freemarker-java8:2.0.0")
'com.munich-airport.freemarker:freemarker-java8:jar:2.0.0'
<dependency org="com.munich-airport.freemarker" name="freemarker-java8" rev="2.0.0">
  <artifact name="freemarker-java8" type="jar" />
</dependency>
@Grapes(
@Grab(group='com.munich-airport.freemarker', module='freemarker-java8', version='2.0.0')
)
libraryDependencies += "com.munich-airport.freemarker" % "freemarker-java8" % "2.0.0"
[com.munich-airport.freemarker/freemarker-java8 "2.0.0"]

Dependencies

compile (1)

Group / Artifact Type Version
org.freemarker : freemarker jar 2.3.23

test (4)

Group / Artifact Type Version
info.cukes : cucumber-java jar 1.2.4
info.cukes : cucumber-junit jar 1.2.4
info.cukes : gherkin jar 2.12.2
junit : junit jar 4.12

Project Modules

There are no modules declared in this project.

Java8 Date/Time Support For FreeMarker

This project is forked from the original but mostly "dead" project of amedia. See the original project here.

This is a tiny Java library that adds basic support for the new Java 8 date/time api to FreeMarker. It is not a perfect solution as FreeMarker doesn’t support adding custom built-ins. Hopefully FreeMarker will add native support in the future, but there are no implementation being worked on at the moment (http://freemarker.org/contribute.html).

The library has basic formatting support for all classes in the java.time api introduced in Java 8, using the new java.time.format.DateTimeFormatter. We have also introduced some comparison methods.

Requirements

Java 8 or higher. Tested on Freemarker 2.3.23, but should at least work fine for all 2.3.x versions. Please file an issue if you have problems with other versions.

Installation

freemarker-java-8 is deployed to the Maven Central Repository. You can include the package in your Maven POM like this :

<dependency>
    <groupId>com.munich-airport.freemarker</groupId>
    <artifactId>freemarker-java8</artifactId>
    <version>2.0.0</version>
</dependency>

Make sure to replace the version with the current version found in the pom.

Usage

You need to configure FreeMarker with our package by adding the Java8ObjectWrapper.

this.configuration = new Configuration(); // Or get the configuration from your framework like DropWizard or Spring Boot.
final Java8Configuration java8Configuration = Java8Configuration.defaultConfiguration();
// Configure the java8 module
// e.g.: java8Configuration.setTimezoneStrategy(SystemTimezoneStrategy.INSTANCE);
this.configuration.setObjectWrapper(new Java8ObjectWrapper(Configuration.VERSION_2_3_23, java8Configuration));

Usage within Spring

Within a Spring project you can add this configuration class to your project:

import no.api.freemarker.java8.Java8ObjectWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;

@Configuration
public class FreemarkerConfig extends FreeMarkerAutoConfiguration.FreeMarkerWebConfiguration {

    @Autowired
    private freemarker.template.Configuration configuration;

    @PostConstruct
    public void postConstruct() {
        final Java8Configuration java8Configuration = Java8Configuration.defaultConfiguration();
        configuration.setObjectWrapper(
                new Java8ObjectWrapper(freemarker.template.Configuration.getVersion(), java8Configuration)); // VERSION_2_3_26
    }

}

java.time support

We had to cheat a little bit to add format methods to our date.time classes. This is why you will see that our syntax differs from the default FreeMarker built-ins.

All format methods uses the java.time.format.DateTimeFormatter for formatting. For sake of completion we also added a isEqual(…​) to LocalTime instances. All bean methods of the java.time classes are still supported.

Table 1. java.time template methods
java.time class methods comment example

Clock

format()

This is a simple implementation where format just prints the toString() value of the object.

${myclock.format()}

Instant

format()

This is a simple implementation where format just prints the toString() value of the object.

${myinstant.format()}

LocalDate

format(), format(pattern)

Allows you to print a LocalDate on a default pattern, or by providing a custom pattern or a builtin format style or the static field name of the DateTimeFormatter class.

${mylocaldate.format()}, ${mylocaldate.format('yyyy MM dd')} or ${mylocaldate.format('FULL_DATE')} or ${mylocaldate.format('ISO_DATE')}

LocalDateTime

format(), format(pattern)

Allows you to print a LocalDateTime on a default pattern, or by providing a custom pattern or a builtin format style or the static field name of the DateTimeFormatter class.

${mylocaldatetime.format()}, ${mylocaldatetime.format('yyyy-MM-dd HH : mm : ss')} or ${mylocaldatetime.format('MEDIUM_DATETIME')} or ${mylocaldatetime.format('ISO_DATE_TIME')}

LocalTime

format(), format(pattern)

Allows you to print a LocalTime on a default pattern, or by providing a custom pattern or a builtin format style or the static field name of the DateTimeFormatter class.

${mylocaltime.format()}, ${mylocaltime.format('HH : mm : ss')} or ${mylocaltime.format('SHORT_TIME')} or ${mylocaltime.format('ISO_TIME')}

MonthDay

format(), format(pattern)

Allows you to print a MonthDay on a default pattern or by providing a custom pattern.

${mymonthday.format()} or ${mymonthday.format('MM dd')}

OffsetDateTime

format(), format(pattern)

Allows you to print a OffsetDateTime on a default pattern, or by providing a custom pattern or a builtin format style or the static field name of the DateTimeFormatter class.

${myoffsetdatetime.format()}, ${myoffsetdatetime.format('yyyy MM dd HH mm ss')} or ${myoffsetdatetime.format('FULL_DATETIME')} or ${myoffsetdatetime.format('IOS_OFFSET_DATE_TIME')}

OffsetTime

format(), format(pattern)

Allows you to print a OffsetTime on a default pattern, or by providing a custom pattern or a builtin format style or the static field name of the DateTimeFormatter class.

${myoffsettime.format()}, ${myoffsettime.format('HH mm ss')} or ${myoffsettime.format('MEDIUM_TIME')} or ${myoffsettime.format('IOS_OFFSET_TIME')}

Year

format(), format(pattern)

Allows you to print a Year on a default pattern or by providing a custom pattern.

${myyear.format()} or ${myyear.format('yyyy')}

YearMonth

format(), format(pattern)

Allows you to print a YearMonth on a default pattern or by providing a custom pattern.

${myyear.format()} or ${myyear.format('yyyy MM')}

ZonedDateTime

format(), format(pattern), format(pattern, zoneId)

Allows you to print a ZonedDateTime on a default pattern/timezone (see timezone strategies), or by providing a custom pattern or a builtin format style or the static field name of the DateTimeFormatter class.

${myzoneddatetime.format()} or ${myzoneddatetime.format('yyyy-MM-dd Z')} or ${myzoneddatetime.format('yyyy-MM-dd Z', 'Asia/Seoul')} or ${myzoneddatetime.format('ISO_ZONED_DATE_TIME', 'Asia/Seoul')}

ZoneId

format(), format(textStyle), format(textstyle, locale)

Prints the ZoneId display name. You can override the textstyle with one of these values [FULL, FULL_STANDALONE, SHORT, SHORT_STANDALONE, NARROW and NARROW_STANDALONE]. You can also override the locale, but Java only seems to have locale support for a few languages.

${myzoneid.format()} or ${myzoneid.format('short')} or ${myzoneid.format('short', 'no-NO')}

ZoneOffset

format(), format(textStyle)

Prints the ZoneOffset display name. You can override the textstyle with one of these values [FULL, FULL_STANDALONE, SHORT, SHORT_STANDALONE, NARROW and NARROW_STANDALONE]. You can also override the locale, but Java only seems to have locale support for a few languages.

${myzoneoffset.format()} or ${myzoneoffset.format('short')} or ${myzoneoffset.format('short', 'no-NO')}

Table 2. java.time comparison methods
java.time class methods comment example

LocalTime

isEqual(<LocalTime object>)

Can compare two LocalTime objects for equality.

${localTime.isEqual(anotherlocalTime)}

Table 3. supported default patterns
pattern

LONG_DATE

LONG_DATETIME

LONG_TIME

MEDIUM_DATE

MEDIUM_DATETIME

MEDIUM_TIME

SHORT_DATE

SHORT_DATETIME

SHORT_TIME

Timezone Strategies

Prior to version 2.0.0 all ZonedDateTime instances formatted using format() or format(pattern) were translated into the ZoneId retrieved by Environment.getCurrentEnvironment().getTimezone().toZoneId(). This leads to unexpected behavior as the purpose of ZonedDateTime is to have an instant in a specific timezone. Otherwise LocalDateTime could be used. From version 2.0.0 onwards, this behavior can be changed by providing a Java8Configuration with a specific TimezoneStrategy when creating the Java8ObjectWrapper. Due to backwards compability this behavior is still present when creating a Java8ObjectWrapper without a Java8Configuration. The Java8Configuration.defaultConfiguration() however uses a different TimezoneStrategy. There are currently 4 builtin strategies:

  1. EnvironmentTimezoneStrategy: Always uses the ZoneId provided by the Environment.getCurrentEnvironment(). This is the default strategy for version < 2.0.0. This strategy is used when creating a Java8ObjectWrapper without a Java8Configuration

  2. KeepingTimezoneStrategy: Does not change the ZoneId. This is the default strategy used when creating a Java8Configuration.defaultConfiguration().

  3. StaticTimezoneStrategy: Always uses the ZoneId provided when constructing this strategy.

  4. SystemTimezoneStrategy: Always uses the ZoneId provided by ZoneId.systemDefault()

com.munich-airport.freemarker

Flughafen München GmbH

Versions

Version
2.0.0