class TimezoneFunction extends Scalar<Long, Object> {

    public static final String NAME = "timezone";
    private static final ZoneId UTC = ZoneId.of("UTC");
    private final DataType returnType;

    public static void register(Functions.Builder module) {<FILL_FUNCTION_BODY>}

    private TimezoneFunction(Signature signature, BoundSignature boundSignature) {
        super(signature, boundSignature);
        this.returnType = boundSignature.returnType();
    }

    @Override
    public Long evaluate(TransactionContext txnCtx, NodeContext nodeCtx, Input<Object>... args) {
        assert args.length == 2 : String.format(Locale.ENGLISH,
                                                "number of arguments must be 2, got %d instead",
                                                args.length);
        String zoneStr = (String) args[0].value();
        if (zoneStr == null) {
            return null;
        }
        ZoneId zoneId;
        try {
            zoneId = ZoneId.of(zoneStr);
        } catch (DateTimeException e) {
            throw new IllegalArgumentException(String.format(Locale.ENGLISH,
                                                             " time zone \"%s\" not recognized",
                                                             zoneStr));
        }
        Number utcTimestamp = (Number) args[1].value();
        if (utcTimestamp == null) {
            return null;
        }

        Instant instant = Instant.ofEpochMilli(utcTimestamp.longValue());
        boolean paramHadTimezone = returnType == DataTypes.TIMESTAMP;
        ZoneId srcZoneId = paramHadTimezone ? zoneId : UTC;
        ZoneId dstZoneId = paramHadTimezone ? UTC : zoneId;
        ZonedDateTime zonedDateTime = instant.atZone(srcZoneId).withZoneSameLocal(dstZoneId);
        return zonedDateTime.toInstant().toEpochMilli();
    }
}

        module.add(
            Signature.scalar(
                NAME,
                DataTypes.STRING.getTypeSignature(),
                DataTypes.TIMESTAMPZ.getTypeSignature(),
                DataTypes.TIMESTAMP.getTypeSignature()
            ),
            TimezoneFunction::new
        );
        module.add(
            Signature.scalar(
                NAME,
                DataTypes.STRING.getTypeSignature(),
                DataTypes.TIMESTAMP.getTypeSignature(),
                DataTypes.TIMESTAMPZ.getTypeSignature()
            ),
            TimezoneFunction::new
        );
        module.add(
            Signature.scalar(
                NAME,
                DataTypes.STRING.getTypeSignature(),
                DataTypes.LONG.getTypeSignature(),
                DataTypes.TIMESTAMPZ.getTypeSignature()
            ),
            TimezoneFunction::new
        );
    
<methods>public BoundSignature boundSignature() ,public Scalar<java.lang.Long,java.lang.Object> compile(List<io.crate.expression.symbol.Symbol>, java.lang.String, io.crate.role.Roles) ,public transient abstract java.lang.Long 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