Skip to content

Commit

Permalink
moved precision time calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
EpsilonPrime committed Jan 11, 2025
1 parent 363a610 commit f139052
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 42 deletions.
45 changes: 8 additions & 37 deletions expr/literals.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
// via ==
type PrimitiveLiteralValue interface {
bool | int8 | int16 | ~int32 | ~int64 |
float32 | float64 | ~string
float32 | float64 | ~string
}

type nestedLiteral interface {
Expand Down Expand Up @@ -156,7 +156,7 @@ func (t *PrimitiveLiteral[T]) String() string {
return fmt.Sprintf("%s(%s)", t.Type.String(), t.ValueString())
}
func (t *PrimitiveLiteral[T]) ValueString() string {
if lit, ok := any(t.Value).(types.TimeConverter); ok {
if lit, ok := any(t.Value).(types.TimePrinter); ok {
return lit.ToTimeString()
}
return fmt.Sprintf("%v", t.Value)
Expand Down Expand Up @@ -450,42 +450,13 @@ type ProtoLiteral struct {
Type types.Type
}

func timeFromPrecisionUnits(units int64, precision types.TimePrecision) time.Time {
var tm time.Time
switch precision {
case types.PrecisionSeconds:
tm = time.Unix(units, 0)
case types.PrecisionDeciSeconds:
tm = time.Unix(units/10, units%10*100000000)
case types.PrecisionCentiSeconds:
tm = time.Unix(units/100, units%100*10000000)
case types.PrecisionMilliSeconds:
tm = time.UnixMilli(units)
case types.PrecisionEMinus4Seconds:
tm = time.Unix(units/10000, units%10000*100000)
case types.PrecisionEMinus5Seconds:
tm = time.Unix(units/100000, units%100000*10000)
case types.PrecisionMicroSeconds:
tm = time.UnixMicro(units)
case types.PrecisionEMinus7Seconds:
tm = time.Unix(units/10000000, units%10000000*100)
case types.PrecisionEMinus8Seconds:
tm = time.Unix(units/100000000, units%100000000*10)
case types.PrecisionNanoSeconds:
tm = time.Unix(units/1000000000, units%1000000000)
default:
panic("unsupported precision")
}
return tm
}

func (t *ProtoLiteral) ValueString() string {
switch literalType := t.Type.(type) {
case *types.PrecisionTimestampType:
tm := timeFromPrecisionUnits(t.Value.(int64), literalType.Precision)
tm := types.Timestamp(t.Value.(int64)).ToPrecisionTime(literalType.Precision)
return tm.UTC().Format("2006-01-02 15:04:05.999999999")
case *types.PrecisionTimestampTzType:
tm := timeFromPrecisionUnits(t.Value.(int64), literalType.Precision)
tm := types.TimestampTz(t.Value.(int64)).ToPrecisionTime(literalType.Precision)
return tm.UTC().Format(time.RFC3339Nano)
case *types.DecimalType:
return decimalBytesToString([16]byte(t.Value.([]byte)), literalType.Scale)
Expand Down Expand Up @@ -610,7 +581,7 @@ func getNullability(nullable bool) types.Nullability {

type newPrimitiveLiteralTypes interface {
bool | int8 | int16 | ~int32 | ~int64 |
float32 | float64 | string
float32 | float64 | string
}

func NewPrimitiveLiteral[T newPrimitiveLiteralTypes](val T, nullable bool) Literal {
Expand Down Expand Up @@ -722,9 +693,9 @@ func NewFixedBinaryLiteral(val types.FixedBinary, nullable bool) *ByteSliceLiter

type allLiteralTypes interface {
PrimitiveLiteralValue | nestedLiteral | MapLiteralValue |
[]byte | types.UUID | types.FixedBinary | *types.IntervalYearToMonth |
*types.IntervalDayToSecond | *types.VarChar | *types.Decimal | *types.UserDefinedLiteral |
*types.PrecisionTimestamp | *types.PrecisionTimestampTz
[]byte | types.UUID | types.FixedBinary | *types.IntervalYearToMonth |
*types.IntervalDayToSecond | *types.VarChar | *types.Decimal | *types.UserDefinedLiteral |
*types.PrecisionTimestamp | *types.PrecisionTimestampTz
}

func NewLiteral[T allLiteralTypes](val T, nullable bool) (Literal, error) {
Expand Down
2 changes: 1 addition & 1 deletion expr/string_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func TestLiteralToValueString(t *testing.T) {
{literal.NewString("99.30"), "99.30"},
{MustLiteral(literal.NewDate(365)), "1971-01-01"},
{MustLiteral(literal.NewTimeFromString("12:34:56")), "12:34:56"},
{MustLiteral(literal.NewTimestampFromString("2021-03-05T12:34:56")), "2021-03-05T12:34:56Z"},
{MustLiteral(literal.NewTimestampFromString("2021-03-05T12:34:56")), "2021-03-05 12:34:56"},
{MustLiteral(literal.NewTimestampTZFromString("2021-03-05T12:34:56")), "2021-03-05T12:34:56Z"},
// Test the first implementation.
{MustLiteral(literal.NewIntervalYearsToMonth(5, 4)), "5 years, 4 months"},
Expand Down
60 changes: 56 additions & 4 deletions types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,13 @@ type (
}

TimeConverter interface {
// ToTime converts the current value into a time.Time assuming microsecond precision.
ToTime() time.Time
// ToPrecisionTime converts the current value using the provided precision into a time.Time.
ToPrecisionTime(precision TimePrecision) time.Time
}

TimePrinter interface {
// ToTimeString returns a human consumable version of the current value.
ToTimeString() string
}
Expand Down Expand Up @@ -1560,17 +1567,62 @@ func (d Date) ToTimeString() string {
return date.String()

Check warning on line 1567 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1564-L1567

Added lines #L1564 - L1567 were not covered by tests
}

func timeFromPrecisionUnits(units int64, precision TimePrecision) time.Time {
var tm time.Time
switch precision {
case PrecisionSeconds:
tm = time.Unix(units, 0)
case PrecisionDeciSeconds:
tm = time.Unix(units/10, units%10*100000000)
case PrecisionCentiSeconds:
tm = time.Unix(units/100, units%100*10000000)
case PrecisionMilliSeconds:
tm = time.UnixMilli(units)
case PrecisionEMinus4Seconds:
tm = time.Unix(units/10000, units%10000*100000)
case PrecisionEMinus5Seconds:
tm = time.Unix(units/100000, units%100000*10000)
case PrecisionMicroSeconds:
tm = time.UnixMicro(units)
case PrecisionEMinus7Seconds:
tm = time.Unix(units/10000000, units%10000000*100)
case PrecisionEMinus8Seconds:
tm = time.Unix(units/100000000, units%100000000*10)
case PrecisionNanoSeconds:
tm = time.Unix(units/1000000000, units%1000000000)
default:
panic("unsupported precision")

Check warning on line 1594 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1570-L1594

Added lines #L1570 - L1594 were not covered by tests
}
return tm

Check warning on line 1596 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1596

Added line #L1596 was not covered by tests
}

func (t Time) ToTimeString() string {
tm := time.UnixMicro(int64(t))
return tm.UTC().Format(time.TimeOnly)

Check warning on line 1601 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1599-L1601

Added lines #L1599 - L1601 were not covered by tests
}

func (t Timestamp) ToTime() time.Time {
return time.UnixMicro(int64(t))

Check warning on line 1605 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1604-L1605

Added lines #L1604 - L1605 were not covered by tests
}

func (t Timestamp) ToPrecisionTime(precision TimePrecision) time.Time {
return timeFromPrecisionUnits(int64(t), precision)

Check warning on line 1609 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1608-L1609

Added lines #L1608 - L1609 were not covered by tests
}

func (t Timestamp) ToTimeString() string {
tm := time.UnixMicro(int64(t))
return tm.UTC().Format(time.RFC3339)
tm := any(t).(TimeConverter).ToTime()
return tm.UTC().Format("2006-01-02 15:04:05.999999999")

Check warning on line 1614 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1612-L1614

Added lines #L1612 - L1614 were not covered by tests
}

func (t TimestampTz) ToTime() time.Time {
return time.UnixMicro(int64(t))

Check warning on line 1618 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1617-L1618

Added lines #L1617 - L1618 were not covered by tests
}

func (t TimestampTz) ToPrecisionTime(precision TimePrecision) time.Time {
return timeFromPrecisionUnits(int64(t), precision)

Check warning on line 1622 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1621-L1622

Added lines #L1621 - L1622 were not covered by tests
}

func (t TimestampTz) ToTimeString() string {
tm := time.UnixMicro(int64(t))
return tm.UTC().Format(time.RFC3339)
tm := any(t).(TimeConverter).ToTime()
return tm.UTC().Format(time.RFC3339Nano)

Check warning on line 1627 in types/types.go

View check run for this annotation

Codecov / codecov/patch

types/types.go#L1625-L1627

Added lines #L1625 - L1627 were not covered by tests
}

0 comments on commit f139052

Please sign in to comment.