func Now(_ *transformctx.Ctx) (string, error) {
	return rfc3339(time.Now().UTC(), true), nil
}
Now returns the current time in UTC in RFC3339 format.
package customfuncs
import (
	"fmt"
	"strconv"
	"time"
	"github.com/jf-tech/go-corelib/caches"
	"github.com/jf-tech/go-corelib/times"
	"github.com/jf-tech/omniparser/transformctx"
)
const (
	rfc3339NoTZ = "2006-01-02T15:04:05"
	second      = "SECOND"
	millisecond = "MILLISECOND"
)
func parseDateTime(datetime, layout string, layoutHasTZ bool, fromTZ, toTZ string) (time.Time, bool, error) {
	var t time.Time
	var hasTZ bool
	var err error
	if layout == "" {
		t, hasTZ, err = times.SmartParse(datetime)
		if err != nil {
			return time.Time{}, false, err
		}
	} else {
		t, err = time.Parse(layout, datetime)
		if err != nil {
			return time.Time{}, false, err
		}
		hasTZ = layoutHasTZ
	}
	if !hasTZ && fromTZ != "" {
		t, err = times.OverwriteTZ(t, fromTZ)
		if err != nil {
			return time.Time{}, false, err
		}
		hasTZ = true
	}
	if toTZ != "" {
		if hasTZ {
			t, err = times.ConvertTZ(t, toTZ)
		} else {
			t, err = times.OverwriteTZ(t, toTZ)
			hasTZ = true
		}
		if err != nil {
			return time.Time{}, false, err
		}
	}
	return t, hasTZ, nil
}
func rfc3339(t time.Time, hasTZ bool) string {
	if hasTZ {
		return t.Format(time.RFC3339)
	}
	return t.Format(rfc3339NoTZ)
}
func DateTimeToRFC3339(_ *transformctx.Ctx, datetime, fromTZ, toTZ string) (string, error) {
	if datetime == "" {
		return "", nil
	}
	t, hasTZ, err := parseDateTime(datetime, "", false, fromTZ, toTZ)
	if err != nil {
		return "", err
	}
	return rfc3339(t, hasTZ), nil
}
func DateTimeLayoutToRFC3339(_ *transformctx.Ctx, datetime, layout, layoutTZ, fromTZ, toTZ string) (string, error) {
	layoutTZFlag := false
	if layout != "" && layoutTZ != "" {
		var err error
		layoutTZFlag, err = strconv.ParseBool(layoutTZ)
		if err != nil {
			return "", err
		}
	}
	if datetime == "" {
		return "", nil
	}
	t, hasTZ, err := parseDateTime(datetime, layout, layoutTZFlag, fromTZ, toTZ)
	if err != nil {
		return "", err
	}
	return rfc3339(t, hasTZ), nil
}
const (
	epochUnitMilliseconds = "MILLISECOND"
	epochUnitSeconds      = "SECOND"
)
func DateTimeToEpoch(_ *transformctx.Ctx, datetime, fromTZ, unit string) (string, error) {
	if datetime == "" {
		return "", nil
	}
	t, _, err := parseDateTime(datetime, "", false, fromTZ, "")
	if err != nil {
		return "", err
	}
	switch unit {
	case epochUnitMilliseconds:
		return strconv.FormatInt(t.UnixNano()/int64(time.Millisecond), 10), nil
	case epochUnitSeconds:
		return strconv.FormatInt(t.Unix(), 10), nil
	default:
		return "", fmt.Errorf("unknown epoch unit '%s'", unit)
	}
}
func EpochToDateTimeRFC3339(_ *transformctx.Ctx, epoch, unit string, tz ...string) (string, error) {
	if epoch == "" {
		return "", nil
	}
	if len(tz) > 1 {
		return "", fmt.Errorf("cannot specify tz argument more than once")
	}
	n, err := strconv.ParseInt(epoch, 10, 64)
	if err != nil {
		return "", err
	}
	timezone := "UTC"
	if len(tz) == 1 {
		timezone = tz[0]
	}
	loc, err := caches.GetTimeLocation(timezone)
	if err != nil {
		return "", err
	}
	var t time.Time
	switch unit {
	case epochUnitSeconds:
		t = time.Unix(n, 0)
	case epochUnitMilliseconds:
		t = time.Unix(0, n*(int64(time.Millisecond)))
	default:
		return "", fmt.Errorf("unknown epoch unit '%s'", unit)
	}
	return rfc3339(t.In(loc), true), nil
}