package pgtype
import (
)
type TimeScanner interface {
ScanTime(v Time) error
}
type TimeValuer interface {
TimeValue() (Time, error)
}
type Time struct {
Microseconds int64
Valid bool
}
func ( *Time) ( Time) error {
* =
return nil
}
func ( Time) () (Time, error) {
return , nil
}
func ( *Time) ( any) error {
if == nil {
* = Time{}
return nil
}
switch src := .(type) {
case string:
:= scanPlanTextAnyToTimeScanner{}.Scan([]byte(), )
if != nil {
.Microseconds = 0
.Valid = false
}
return
}
return fmt.Errorf("cannot scan %T", )
}
func ( Time) () (driver.Value, error) {
if !.Valid {
return nil, nil
}
, := TimeCodec{}.PlanEncode(nil, 0, TextFormatCode, ).Encode(, nil)
if != nil {
return nil,
}
return string(),
}
type TimeCodec struct{}
func (TimeCodec) ( int16) bool {
return == TextFormatCode || == BinaryFormatCode
}
func (TimeCodec) () int16 {
return BinaryFormatCode
}
func (TimeCodec) ( *Map, uint32, int16, any) EncodePlan {
if , := .(TimeValuer); ! {
return nil
}
switch {
case BinaryFormatCode:
return encodePlanTimeCodecBinary{}
case TextFormatCode:
return encodePlanTimeCodecText{}
}
return nil
}
type encodePlanTimeCodecBinary struct{}
func (encodePlanTimeCodecBinary) ( any, []byte) ( []byte, error) {
, := .(TimeValuer).TimeValue()
if != nil {
return nil,
}
if !.Valid {
return nil, nil
}
return pgio.AppendInt64(, .Microseconds), nil
}
type encodePlanTimeCodecText struct{}
func (encodePlanTimeCodecText) ( any, []byte) ( []byte, error) {
, := .(TimeValuer).TimeValue()
if != nil {
return nil,
}
if !.Valid {
return nil, nil
}
:= .Microseconds
:= / microsecondsPerHour
-= * microsecondsPerHour
:= / microsecondsPerMinute
-= * microsecondsPerMinute
:= / microsecondsPerSecond
-= * microsecondsPerSecond
:= fmt.Sprintf("%02d:%02d:%02d.%06d", , , , )
return append(, ...), nil
}
func (TimeCodec) ( *Map, uint32, int16, any) ScanPlan {
switch {
case BinaryFormatCode:
switch .(type) {
case TimeScanner:
return scanPlanBinaryTimeToTimeScanner{}
case TextScanner:
return scanPlanBinaryTimeToTextScanner{}
}
case TextFormatCode:
switch .(type) {
case TimeScanner:
return scanPlanTextAnyToTimeScanner{}
}
}
return nil
}
type scanPlanBinaryTimeToTimeScanner struct{}
func (scanPlanBinaryTimeToTimeScanner) ( []byte, any) error {
:= ().(TimeScanner)
if == nil {
return .ScanTime(Time{})
}
if len() != 8 {
return fmt.Errorf("invalid length for time: %v", len())
}
:= int64(binary.BigEndian.Uint64())
return .ScanTime(Time{Microseconds: , Valid: true})
}
type scanPlanBinaryTimeToTextScanner struct{}
func (scanPlanBinaryTimeToTextScanner) ( []byte, any) error {
, := ().(TextScanner)
if ! {
return ErrScanTargetTypeChanged
}
if == nil {
return .ScanText(Text{})
}
if len() != 8 {
return fmt.Errorf("invalid length for time: %v", len())
}
:= int64(binary.BigEndian.Uint64())
:= Time{Microseconds: , Valid: true}
, := TimeCodec{}.PlanEncode(nil, 0, TextFormatCode, ).Encode(, nil)
if != nil {
return
}
return .ScanText(Text{String: string(), Valid: true})
}
type scanPlanTextAnyToTimeScanner struct{}
func (scanPlanTextAnyToTimeScanner) ( []byte, any) error {
:= ().(TimeScanner)
if == nil {
return .ScanTime(Time{})
}
:= string()
if len() < 8 || [2] != ':' || [5] != ':' {
return fmt.Errorf("cannot decode %v into Time", )
}
, := strconv.ParseInt([0:2], 10, 64)
if != nil {
return fmt.Errorf("cannot decode %v into Time", )
}
:= * microsecondsPerHour
, := strconv.ParseInt([3:5], 10, 64)
if != nil {
return fmt.Errorf("cannot decode %v into Time", )
}
+= * microsecondsPerMinute
, := strconv.ParseInt([6:8], 10, 64)
if != nil {
return fmt.Errorf("cannot decode %v into Time", )
}
+= * microsecondsPerSecond
if len() > 9 {
if [8] != '.' || len() > 15 {
return fmt.Errorf("cannot decode %v into Time", )
}
:= [9:]
, := strconv.ParseInt(, 10, 64)
if != nil {
return fmt.Errorf("cannot decode %v into Time", )
}
for := len(); < 6; ++ {
*= 10
}
+=
}
return .ScanTime(Time{Microseconds: , Valid: true})
}
func ( TimeCodec) ( *Map, uint32, int16, []byte) (driver.Value, error) {
return codecDecodeToTextFormat(, , , , )
}
func ( TimeCodec) ( *Map, uint32, int16, []byte) (any, error) {
if == nil {
return nil, nil
}
var Time
:= codecScan(, , , , , &)
if != nil {
return nil,
}
return , nil
}