There are 4 scalar types:
For each scalar type is a TemplateTypeModel interface, where Type is the name of the type. These interfaces define only one method: type getAsType();. This returns the value of the variable with the Java type (boolean, Number, String and Date respectively).
For historical reasons the interface for string scalars is called TemplateScalarModel, not TemplateStringModel.
A trivial implementation of these interfaces are available in freemarker.template package with SimpleType class name. However, there is no SimpleBooleanModel; to represent the boolean values you can use the TemplateBooleanModel.TRUE and TemplateBooleanModel.FALSE singletons.
For historical reasons the class for string scalars is called SimpleScalar, not SimpleString.
Scalars are immutable within FTL. When you set the value of a variable in a template, then you replace the TemplateTypeModel instance with another instance, and don't change the value stored in the original instance.
There is a complication around date types, because Java API usually does not differentiate java.util.Date-s that store only the date part (April 4, 2003), only the time part (10:19:18 PM), or both (April 4, 2003 10:19:18 PM). To display a date variable as text correctly, FreeMarker must know what parts of the java.util.Date stores meaningful information, and what parts are unused. Unfortunately, the only place where the Java API cleanly tells this, is with database handling (SQL), because databases typically has separated date, time and timestamp (aka date-time) types, and java.sql has 3 corresponding java.util.Date subclasses for them.
TemplateDateModel interface has two methods: java.util.Date getAsDate() and int getDateType(). A typical implementation of this interface, stores a java.util.Date object, plus an integer that tells the "database style type". The value of this integer must be a constant from the TemplateDateModel interface: DATE, TIME, DATETIME and UNKNOWN.
What is UNKNOWN? As we told earlier, java.lang and java.util classes are usually converted automatically into TemplateModel implementations, be so called object wrappers. If the object wrapper faces a java.util.Date, that is not an instance of a java.sql date class, it can't decide what the "database style type" is, so it uses UNKNOWN. Later, if the template has to use this variable, and the "database style type" is needed for the operation, it will stop with error. To prevent this, for the problematic variables the template author must help FreeMarker to decide the "database style type", by using the date, time or datetime built-ins. Note that if you use string built-in with format parameter, as foo?string("MM/dd/yyyy"), then FreeMarker don't need to know the "database style type".