class DateFormatFunction extends Scalar<String, Object> {

    public static final String NAME = "date_format";
    public static final String DEFAULT_FORMAT = "%Y-%m-%dT%H:%i:%s.%fZ";

    public static void register(Functions.Builder module) {
        List<DataType<?>> supportedTimestampTypes = List.of(
            DataTypes.TIMESTAMPZ, DataTypes.TIMESTAMP, DataTypes.LONG);
        for (DataType<?> dataType : supportedTimestampTypes) {
            // without format
            module.add(
                Signature.scalar(
                    NAME,
                    dataType.getTypeSignature(),
                    DataTypes.STRING.getTypeSignature()
                ), DateFormatFunction::new
            );

            // with format
            module.add(
                Signature.scalar(
                    NAME,
                    DataTypes.STRING.getTypeSignature(),
                    dataType.getTypeSignature(),
                    DataTypes.STRING.getTypeSignature()
                ), DateFormatFunction::new
            );

            // time zone aware variant
            module.add(
                Signature.scalar(
                    NAME,
                    DataTypes.STRING.getTypeSignature(),
                    DataTypes.STRING.getTypeSignature(),
                    dataType.getTypeSignature(),
                    DataTypes.STRING.getTypeSignature()
                ), DateFormatFunction::new
            );
        }
    }

    public DateFormatFunction(Signature signature, BoundSignature boundSignature) {
        super(signature, boundSignature);
    }

    @Override
    public String evaluate(TransactionContext txnCtx, NodeContext nodeCtx, Input<Object>... args) {<FILL_FUNCTION_BODY>}
}

        String format;
        Input<?> timezoneLiteral = null;
        if (args.length == 1) {
            format = DEFAULT_FORMAT;
        } else {
            format = (String) args[0].value();
            if (format == null) {
                return null;
            }
            if (args.length == 3) {
                timezoneLiteral = args[1];
            }
        }
        Object tsValue = args[args.length - 1].value();
        if (tsValue == null) {
            return null;
        }
        Long timestamp = DataTypes.TIMESTAMPZ.sanitizeValue(tsValue);
        DateTimeZone timezone = DateTimeZone.UTC;
        if (timezoneLiteral != null) {
            Object timezoneValue = timezoneLiteral.value();
            if (timezoneValue == null) {
                return null;
            }
            timezone = TimeZoneParser.parseTimeZone((String) timezoneValue);
        }
        DateTime dateTime = new DateTime(timestamp, timezone);
        return TimestampFormatter.format(format, dateTime);
    
<methods>public BoundSignature boundSignature() ,public Scalar<java.lang.String,java.lang.Object> compile(List<io.crate.expression.symbol.Symbol>, java.lang.String, io.crate.role.Roles) ,public transient abstract java.lang.String evaluate(io.crate.metadata.TransactionContext, io.crate.metadata.NodeContext, Input<java.lang.Object>[]) ,public io.crate.expression.symbol.Symbol normalizeSymbol(io.crate.expression.symbol.Function, io.crate.metadata.TransactionContext, io.crate.metadata.NodeContext) ,public io.crate.metadata.functions.Signature signature() <variables>public static final Set<io.crate.metadata.Scalar.Feature> DETERMINISTIC_AND_COMPARISON_REPLACEMENT,public static final Set<io.crate.metadata.Scalar.Feature> DETERMINISTIC_ONLY,public static final Set<io.crate.metadata.Scalar.Feature> NO_FEATURES,protected final non-sealed BoundSignature boundSignature,protected final non-sealed io.crate.metadata.functions.Signature signature