package datatypes

import (
	
	
	
	
	
	

	
	
)

// Time is time data type.
type Time time.Duration

// NewTime is a constructor for Time and returns new Time.
func (, , ,  int) Time {
	return newTime(, , , )
}

func newTime(, , ,  int) Time {
	return Time(
		time.Duration()*time.Hour +
			time.Duration()*time.Minute +
			time.Duration()*time.Second +
			time.Duration()*time.Nanosecond,
	)
}

// GormDataType returns gorm common data type. This type is used for the field's column type.
func (Time) () string {
	return "time"
}

// GormDBDataType returns gorm DB data type based on the current using database.
func (Time) ( *gorm.DB,  *schema.Field) string {
	switch .Dialector.Name() {
	case "mysql":
		return "TIME"
	case "postgres":
		return "TIME"
	case "sqlserver":
		return "TIME"
	case "sqlite":
		return "TEXT"
	default:
		return ""
	}
}

// Scan implements sql.Scanner interface and scans value into Time,
func ( *Time) ( interface{}) error {
	switch v := .(type) {
	case []byte:
		.setFromString(string())
	case string:
		.setFromString()
	case time.Time:
		.setFromTime()
	default:
		return errors.New(fmt.Sprintf("failed to scan value: %v", ))
	}

	return nil
}

func ( *Time) ( string) {
	var , , ,  int
	fmt.Sscanf(, "%02d:%02d:%02d.%09d", &, &, &, &)
	* = newTime(, , , )
}

func ( *Time) ( time.Time) {
	* = newTime(.Hour(), .Minute(), .Second(), .Nanosecond())
}

// Value implements driver.Valuer interface and returns string format of Time.
func ( Time) () (driver.Value, error) {
	return .String(), nil
}

// String implements fmt.Stringer interface.
func ( Time) () string {
	if  := .nanoseconds();  > 0 {
		return fmt.Sprintf("%02d:%02d:%02d.%09d", .hours(), .minutes(), .seconds(), )
	} else {
		// omit nanoseconds unless any value is specified
		return fmt.Sprintf("%02d:%02d:%02d", .hours(), .minutes(), .seconds())
	}
}

func ( Time) () int {
	return int(time.Duration().Truncate(time.Hour).Hours())
}

func ( Time) () int {
	return int((time.Duration() % time.Hour).Truncate(time.Minute).Minutes())
}

func ( Time) () int {
	return int((time.Duration() % time.Minute).Truncate(time.Second).Seconds())
}

func ( Time) () int {
	return int((time.Duration() % time.Second).Nanoseconds())
}

// MarshalJSON implements json.Marshaler to convert Time to json serialization.
func ( Time) () ([]byte, error) {
	return json.Marshal(.String())
}

// UnmarshalJSON implements json.Unmarshaler to deserialize json data.
func ( *Time) ( []byte) error {
	// ignore null
	if string() == "null" {
		return nil
	}
	.setFromString(strings.Trim(string(), `"`))
	return nil
}