in freemarker-core/src/main/java/freemarker/core/ISOLikeTemplateDateFormat.java [51:169]
public ISOLikeTemplateDateFormat(
final String formatString, int parsingStart,
int dateType, boolean zonelessInput,
TimeZone timeZone,
ISOLikeTemplateDateFormatFactory factory, Environment env)
throws InvalidFormatParametersException, UnknownDateTypeFormattingUnsupportedException {
this.factory = factory;
this.env = env;
if (dateType == TemplateDateModel.UNKNOWN) {
throw new UnknownDateTypeFormattingUnsupportedException();
}
this.dateType = dateType;
this.zonelessInput = zonelessInput;
final int ln = formatString.length();
boolean afterSeparator = false;
int i = parsingStart;
int accuracy = DateUtil.ACCURACY_MILLISECONDS;
Boolean showZoneOffset = null;
Boolean forceUTC = Boolean.FALSE;
while (i < ln) {
final char c = formatString.charAt(i++);
if (c == '_' || c == ' ') {
afterSeparator = true;
} else {
if (!afterSeparator) {
throw new InvalidFormatParametersException(
"Missing space or \"_\" before \"" + c + "\" (at char pos. " + i + ").");
}
switch (c) {
case 'h':
case 'm':
case 's':
if (accuracy != DateUtil.ACCURACY_MILLISECONDS) {
throw new InvalidFormatParametersException(
"Character \"" + c + "\" is unexpected as accuracy was already specified earlier "
+ "(at char pos. " + i + ").");
}
switch (c) {
case 'h':
if (isXSMode()) {
throw new InvalidFormatParametersException(
XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE);
}
accuracy = DateUtil.ACCURACY_HOURS;
break;
case 'm':
if (i < ln && formatString.charAt(i) == 's') {
i++;
accuracy = DateUtil.ACCURACY_MILLISECONDS_FORCED;
} else {
if (isXSMode()) {
throw new InvalidFormatParametersException(
XS_LESS_THAN_SECONDS_ACCURACY_ERROR_MESSAGE);
}
accuracy = DateUtil.ACCURACY_MINUTES;
}
break;
case 's':
accuracy = DateUtil.ACCURACY_SECONDS;
break;
}
break;
case 'f':
if (i < ln && formatString.charAt(i) == 'u') {
checkForceUTCNotSet(forceUTC);
i++;
forceUTC = Boolean.TRUE;
break;
}
// Falls through
case 'n':
if (showZoneOffset != null) {
throw new InvalidFormatParametersException(
"Character \"" + c + "\" is unexpected as zone offset visibility was already "
+ "specified earlier. (at char pos. " + i + ").");
}
switch (c) {
case 'n':
if (i < ln && formatString.charAt(i) == 'z') {
i++;
showZoneOffset = Boolean.FALSE;
} else {
throw new InvalidFormatParametersException(
"\"n\" must be followed by \"z\" (at char pos. " + i + ").");
}
break;
case 'f':
if (i < ln && formatString.charAt(i) == 'z') {
i++;
showZoneOffset = Boolean.TRUE;
} else {
throw new InvalidFormatParametersException(
"\"f\" must be followed by \"z\" (at char pos. " + i + ").");
}
break;
}
break;
case 'u':
checkForceUTCNotSet(forceUTC);
forceUTC = null; // means UTC will be used except for zonelessInput
break;
default:
throw new InvalidFormatParametersException(
"Unexpected character, " + StringUtil.jQuote(String.valueOf(c))
+ ". Expected the beginning of one of: h, m, s, ms, nz, fz, u"
+ " (at char pos. " + i + ").");
} // switch
afterSeparator = false;
} // else
} // while
this.accuracy = accuracy;
this.showZoneOffset = showZoneOffset;
this.forceUTC = forceUTC;
this.timeZone = timeZone;
}