func convertOffsets(t time.Time, startDuration string, endDuration string) (time.Time, bool) {
	fromDuration, err := getDeltaAsDuration(startDuration)
	if err != nil {
		return time.Time{}, false
	}
	toDuration, err := getDeltaAsDuration(endDuration)
	if err != nil {
		return time.Time{}, false
	}
	return t.Add(toDuration - fromDuration), true
}
convertOffsets returns the conversion of t to t + (endDuration - startDuration) and a boolean indicating success.
package function
import (
	"errors"
	"fmt"
	"regexp"
	"time"
	"github.com/dolthub/go-mysql-server/sql"
)
var offsetRegex = regexp.MustCompile(`(?m)^(\+|\-)(\d{2}):(\d{2})$`)  
type ConvertTz struct {
	dt     sql.Expression
	fromTz sql.Expression
	toTz   sql.Expression
}
var _ sql.FunctionExpression = (*ConvertTz)(nil)
func NewConvertTz(dt, fromTz, toTz sql.Expression) sql.Expression {
	return &ConvertTz{
		dt:     dt,
		fromTz: fromTz,
		toTz:   toTz,
	}
}
func (c *ConvertTz) Resolved() bool {
	return c.dt.Resolved() && c.fromTz.Resolved() && c.toTz.Resolved()
}
func (c *ConvertTz) String() string {
	return fmt.Sprintf("CONVERT_TZ(%s, %s, %s)", c.dt, c.fromTz, c.toTz)
}
func (c *ConvertTz) Type() sql.Type {
	return sql.Datetime
}
func (c *ConvertTz) IsNullable() bool {
	return true
}
func (c *ConvertTz) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
	from, err := c.fromTz.Eval(ctx, row)
	if err != nil {
		return nil, err
	}
	to, err := c.toTz.Eval(ctx, row)
	if err != nil {
		return nil, err
	}
	dt, err := c.dt.Eval(ctx, row)
	if err != nil {
		return nil, err
	}
	datetime, err := sql.Datetime.ConvertWithoutRangeCheck(dt)
	if err != nil {
		return nil, nil
	}
	fromStr, ok := from.(string)
	if !ok {
		return nil, nil
	}
	toStr, ok := to.(string)
	if !ok {
		return nil, nil
	}
	converted, success := convertTimeZone(datetime, fromStr, toStr)
	if success {
		return sql.Datetime.ConvertWithoutRangeCheck(converted)
	}
	converted, success = convertOffsets(datetime, fromStr, toStr)
	if !success {
		return nil, nil
	}
	return sql.Datetime.ConvertWithoutRangeCheck(converted)
}
func convertTimeZone(datetime time.Time, fromLocation string, toLocation string) (time.Time, bool) {
	fLoc, err := time.LoadLocation(fromLocation)
	if err != nil {
		return time.Time{}, false
	}
	tLoc, err := time.LoadLocation(toLocation)
	if err != nil {
		return time.Time{}, false
	}
	delta := getCopy(datetime, fLoc).Sub(getCopy(datetime, tLoc))
	return datetime.Add(delta), true
}
func getCopy(t time.Time, loc *time.Location) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), loc).UTC()
}