Java library adding support for the Java 8 java.time api to FreeMarker.
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

README.adoc

Java8 Date/Time Support For FreeMarker Build Status

This is a tiny Java library that adds basic support for the new Java 8 date/time api to FreeMarker. Its not a perfect solution as we cannot add built-ins to FreeMarker from external code. 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 som 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>no.api.freemarker</groupId>
    <artifactId>freemarker-java8</artifactId>
    <version>1.1.5</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.
this.configuration.setObjectWrapper(new Java8ObjectWrapper(Configuration.VERSION_2_3_23));

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() {
        configuration.setObjectWrapper(
                new Java8ObjectWrapper(freemarker.template.Configuration.getVersion())); // 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.

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()}

Duration

nano(), seconds()

Gives access to the Duration values

${myduration.seconds}, ${myduration.nano}

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.

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

LocalDateTime

format(), format(pattern)

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

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

LocalTime

format(), format(pattern)

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

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

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.

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

OffsetTime

format(), format(pattern)

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

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

Period

days(), months(), years()

Gives access to the values of the Period object.

${myperiod.days}, ${myperiod.months}, ${myperiod.years}

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 YearMonth on a default pattern/timezone or by providing a custom pattern and timezone.

${myzoneddatetime.format()} or ${myzoneddatetime.format('yyyy-MM-dd Z')} or ${myzoneddatetime.format('yyyy-MM-dd Z', '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

LocalDate

isEqual(<LocalDate object>), isAfter(<LocalDate object>), isBefore(<LocalDate object>)

Can compare two LocalDate objects for equality.

${localDate.isEqual(anotherlocalDate)} or ${localDate.isAfter(anotherlocalDate)} or ${localDate.isBefore(anotherlocalDate)}

LocalDateTime

isEqual(<LocalDateTime object>), isAfter(<LocalDateTime object>), isBefore(<LocalDateTime object>)

Can compare two LocalDateTime objects for equality.

${localDateTime.isEqual(anotherlocalDateTime)} or ${localDateTime.isAfter(anotherlocalDateTime)} or ${localDateTime.isBefore(anotherlocalDateTime)}

LocalTime

isEqual(<LocalTime object>), isAfter(<LocalTime object>), isBefore(<LocalTime object>)

Can compare two LocalTime objects for equality.

${localTime.isEqual(anotherlocalTime)} or ${localTime.isAfter(anotherlocalTime)} or ${localTime.isBefore(anotherlocalTime)}