func (fd *FFDuration) Value() (driver.Value, error) {
	return fd.String(), nil
}
Value implements sql.Valuer
package fftypes
import (
	"context"
	"database/sql/driver"
	"encoding/json"
	"strconv"
	"time"
	"github.com/hyperledger/firefly/internal/i18n"
	"github.com/hyperledger/firefly/internal/log"
)
type FFTime time.Time
type FFDuration time.Duration
func Now() *FFTime {
	t := FFTime(time.Now().UTC())
	return &t
}
func ZeroTime() FFTime {
	return FFTime(time.Time{}.UTC())
}
func UnixTime(unixTime int64) *FFTime {
	if unixTime < 1e10 {
		unixTime *= 1e3  
	}
	if unixTime < 1e15 {
		unixTime *= 1e6  
	}
	t := FFTime(time.Unix(0, unixTime))
	return &t
}
func (ft *FFTime) MarshalJSON() ([]byte, error) {
	if ft == nil || time.Time(*ft).IsZero() {
		return json.Marshal(nil)
	}
	return json.Marshal(ft.String())
}
func ParseString(str string) (*FFTime, error) {
	t, err := time.Parse(time.RFC3339Nano, str)
	if err != nil {
		var unixTime int64
		unixTime, err = strconv.ParseInt(str, 10, 64)
		if err == nil {
			return UnixTime(unixTime), nil
		}
	}
	if err != nil {
		zero := ZeroTime()
		return &zero, i18n.NewError(context.Background(), i18n.MsgTimeParseFail, str)
	}
	ft := FFTime(t)
	return &ft, nil
}
func (ft *FFTime) Time() *time.Time {
	return (*time.Time)(ft)
}
func (ft *FFTime) UnixNano() int64 {
	if ft == nil {
		return 0
	}
	return time.Time(*ft).UnixNano()
}
func (ft *FFTime) UnmarshalText(b []byte) error {
	t, err := ParseString(string(b))
	if err != nil {
		return err
	}
	*ft = *t
	return nil
}
func (ft *FFTime) Scan(src interface{}) error {
	switch src := src.(type) {
	case nil:
		*ft = ZeroTime()
		return nil
	case string:
		t, err := ParseString(src)
		if err != nil {
			return err
		}
		*ft = *t
		return nil
	case int64:
		if src == 0 {
			return nil
		}
		t := UnixTime(src)
		*ft = *t
		return nil
	default:
		return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, ft)
	}
}
func (ft FFTime) Value() (driver.Value, error) {
	if time.Time(ft).IsZero() {
		return int64(0), nil
	}
	return ft.UnixNano(), nil
}
func (ft FFTime) String() string {
	if time.Time(ft).IsZero() {
		return ""
	}
	return time.Time(ft).UTC().Format(time.RFC3339Nano)
}
func (ft *FFTime) Equal(ft2 *FFTime) bool {
	if ft == nil && ft2 == nil {
		return true
	}
	if ft == nil || ft2 == nil {
		return false
	}
	return *ft == *ft2
}
func ParseToDuration(durationString string) time.Duration {
	if durationString == "" {
		return time.Duration(0)
	}
	ffd, err := ParseDurationString(durationString, time.Millisecond)
	if err != nil {
		log.L(context.Background()).Warn(err)
	}
	return time.Duration(ffd)
}
func ParseDurationString(durationString string, def time.Duration) (FFDuration, error) {
	duration, err := time.ParseDuration(durationString)
	if err != nil {
		intVal, err := strconv.ParseInt(durationString, 10, 64)
		if err != nil {
			return 0, i18n.NewError(context.Background(), i18n.MsgDurationParseFail, durationString)
		}
		duration = time.Duration(intVal) * def
	}
	return FFDuration(duration), nil
}
func (fd *FFDuration) MarshalJSON() ([]byte, error) {
	return json.Marshal(time.Duration(*fd).String())
}
func (fd *FFDuration) UnmarshalJSON(b []byte) error {
	var stringVal string
	err := json.Unmarshal(b, &stringVal)
	if err != nil {
		var intVal int64
		err = json.Unmarshal(b, &intVal)
		if err != nil {
			return err
		}
		*fd = FFDuration(intVal) * FFDuration(time.Millisecond)
		return nil
	}
	duration, err := ParseDurationString(stringVal, time.Millisecond)
	if err != nil {
		return err
	}
	*fd = duration
	return nil
}
func (fd *FFDuration) Scan(src interface{}) error {
	switch src := src.(type) {
	case nil:
		*fd = 0
		return nil
	case string:
		duration, err := ParseDurationString(src, time.Millisecond)
		if err != nil {
			return err
		}
		*fd = duration
		return nil
	case int:
		*fd = FFDuration(time.Duration(src) * time.Millisecond)
		return nil
	case int64:
		*fd = FFDuration(time.Duration(src) * time.Millisecond)
		return nil
	default:
		return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, fd)
	}
}