package pgtype

import (
	
	
	
	
	

	
)

const pgTimestamptzHourFormat = "2006-01-02 15:04:05.999999999Z07"
const pgTimestamptzMinuteFormat = "2006-01-02 15:04:05.999999999Z07:00"
const pgTimestamptzSecondFormat = "2006-01-02 15:04:05.999999999Z07:00:00"
const microsecFromUnixEpochToY2K = 946684800 * 1000000

const (
	negativeInfinityMicrosecondOffset = -9223372036854775808
	infinityMicrosecondOffset         = 9223372036854775807
)

type Timestamptz struct {
	Time             time.Time
	Status           Status
	InfinityModifier InfinityModifier
}

func ( *Timestamptz) ( interface{}) error {
	if  == nil {
		* = Timestamptz{Status: Null}
		return nil
	}

	if ,  := .(interface{ () interface{} });  {
		 := .()
		if  !=  {
			return .()
		}
	}

	switch value := .(type) {
	case time.Time:
		* = Timestamptz{Time: , Status: Present}
	case *time.Time:
		if  == nil {
			* = Timestamptz{Status: Null}
		} else {
			return .(*)
		}
	case InfinityModifier:
		* = Timestamptz{InfinityModifier: , Status: Present}
	default:
		if ,  := underlyingTimeType();  {
			return .()
		}
		return fmt.Errorf("cannot convert %v to Timestamptz", )
	}

	return nil
}

func ( Timestamptz) () interface{} {
	switch .Status {
	case Present:
		if .InfinityModifier != None {
			return .InfinityModifier
		}
		return .Time
	case Null:
		return nil
	default:
		return .Status
	}
}

func ( *Timestamptz) ( interface{}) error {
	switch .Status {
	case Present:
		switch v := .(type) {
		case *time.Time:
			if .InfinityModifier != None {
				return fmt.Errorf("cannot assign %v to %T", , )
			}
			* = .Time
			return nil
		default:
			if ,  := GetAssignToDstType();  {
				return .()
			}
			return fmt.Errorf("unable to assign to %T", )
		}
	case Null:
		return NullAssignTo()
	}

	return fmt.Errorf("cannot decode %#v into %T", , )
}

func ( *Timestamptz) ( *ConnInfo,  []byte) error {
	if  == nil {
		* = Timestamptz{Status: Null}
		return nil
	}

	 := string()
	switch  {
	case "infinity":
		* = Timestamptz{Status: Present, InfinityModifier: Infinity}
	case "-infinity":
		* = Timestamptz{Status: Present, InfinityModifier: -Infinity}
	default:
		var  string
		if len() >= 9 && ([len()-9] == '-' || [len()-9] == '+') {
			 = pgTimestamptzSecondFormat
		} else if len() >= 6 && ([len()-6] == '-' || [len()-6] == '+') {
			 = pgTimestamptzMinuteFormat
		} else {
			 = pgTimestamptzHourFormat
		}

		,  := time.Parse(, )
		if  != nil {
			return 
		}

		* = Timestamptz{Time: , Status: Present}
	}

	return nil
}

func ( *Timestamptz) ( *ConnInfo,  []byte) error {
	if  == nil {
		* = Timestamptz{Status: Null}
		return nil
	}

	if len() != 8 {
		return fmt.Errorf("invalid length for timestamptz: %v", len())
	}

	 := int64(binary.BigEndian.Uint64())

	switch  {
	case infinityMicrosecondOffset:
		* = Timestamptz{Status: Present, InfinityModifier: Infinity}
	case negativeInfinityMicrosecondOffset:
		* = Timestamptz{Status: Present, InfinityModifier: -Infinity}
	default:
		 := microsecFromUnixEpochToY2K + 
		 := time.Unix(/1000000, (%1000000)*1000)
		* = Timestamptz{Time: , Status: Present}
	}

	return nil
}

func ( Timestamptz) ( *ConnInfo,  []byte) ([]byte, error) {
	switch .Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}

	var  string

	switch .InfinityModifier {
	case None:
		 = .Time.UTC().Truncate(time.Microsecond).Format(pgTimestamptzSecondFormat)
	case Infinity:
		 = "infinity"
	case NegativeInfinity:
		 = "-infinity"
	}

	return append(, ...), nil
}

func ( Timestamptz) ( *ConnInfo,  []byte) ([]byte, error) {
	switch .Status {
	case Null:
		return nil, nil
	case Undefined:
		return nil, errUndefined
	}

	var  int64
	switch .InfinityModifier {
	case None:
		 := .Time.Unix()*1000000 + int64(.Time.Nanosecond())/1000
		 =  - microsecFromUnixEpochToY2K
	case Infinity:
		 = infinityMicrosecondOffset
	case NegativeInfinity:
		 = negativeInfinityMicrosecondOffset
	}

	return pgio.AppendInt64(, ), nil
}
Scan implements the database/sql Scanner interface.
func ( *Timestamptz) ( interface{}) error {
	if  == nil {
		* = Timestamptz{Status: Null}
		return nil
	}

	switch src := .(type) {
	case string:
		return .DecodeText(nil, []byte())
	case []byte:
		 := make([]byte, len())
		copy(, )
		return .DecodeText(nil, )
	case time.Time:
		* = Timestamptz{Time: , Status: Present}
		return nil
	}

	return fmt.Errorf("cannot scan %T", )
}
Value implements the database/sql/driver Valuer interface.
func ( Timestamptz) () (driver.Value, error) {
	switch .Status {
	case Present:
		if .InfinityModifier != None {
			return .InfinityModifier.String(), nil
		}
		return .Time, nil
	case Null:
		return nil, nil
	default:
		return nil, errUndefined
	}
}

func ( Timestamptz) () ([]byte, error) {
	switch .Status {
	case Null:
		return []byte("null"), nil
	case Undefined:
		return nil, errUndefined
	}

	if .Status != Present {
		return nil, errBadStatus
	}

	var  string

	switch .InfinityModifier {
	case None:
		 = .Time.Format(time.RFC3339Nano)
	case Infinity:
		 = "infinity"
	case NegativeInfinity:
		 = "-infinity"
	}

	return json.Marshal()
}

func ( *Timestamptz) ( []byte) error {
	var  *string
	 := json.Unmarshal(, &)
	if  != nil {
		return 
	}

	if  == nil {
		* = Timestamptz{Status: Null}
		return nil
	}

	switch * {
	case "infinity":
		* = Timestamptz{Status: Present, InfinityModifier: Infinity}
	case "-infinity":
		* = Timestamptz{Status: Present, InfinityModifier: -Infinity}
PostgreSQL uses ISO 8601 for to_json function and casting from a string to timestamptz
		,  := time.Parse(time.RFC3339Nano, *)
		if  != nil {
			return 
		}

		* = Timestamptz{Time: , Status: Present}
	}

	return nil