diff --git a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/SmithyGoDependency.java b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/SmithyGoDependency.java index e0e546c59..f28ef2980 100644 --- a/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/SmithyGoDependency.java +++ b/codegen/smithy-go-codegen/src/main/java/software/amazon/smithy/go/codegen/SmithyGoDependency.java @@ -118,7 +118,7 @@ private static GoDependency relativePackage( private static final class Versions { private static final String GO_STDLIB = "1.15"; private static final String GO_CMP = "v0.5.4"; - private static final String SMITHY_GO = "v0.0.0-20210113172615-49588e1e8525"; + private static final String SMITHY_GO = "v0.5.1-0.20210115041537-09631dea532e"; private static final String GO_JMESPATH = "v0.4.0"; } } diff --git a/time/time.go b/time/time.go index 0a3fbe48c..35a387031 100644 --- a/time/time.go +++ b/time/time.go @@ -2,6 +2,7 @@ package time import ( "context" + "math/big" "time" ) @@ -13,6 +14,8 @@ const ( httpDateFormat = "Mon, 02 Jan 2006 15:04:05 GMT" ) +var millisecondFloat = big.NewFloat(1e3) + // FormatDateTime format value as a date-time (RFC3339 section 5.6) // // Example: 1985-04-12T23:20:50.52Z @@ -43,16 +46,20 @@ func ParseHTTPDate(value string) (time.Time, error) { // FormatEpochSeconds returns value as a Unix time in seconds with with decimal precision // -// Example: 1515531081.1234 +// Example: 1515531081.123 func FormatEpochSeconds(value time.Time) float64 { - return float64(value.UnixNano()) / float64(time.Second) + ms := value.UnixNano() / int64(time.Millisecond) + return float64(ms)/1e3 } // ParseEpochSeconds returns value as a Unix time in seconds with with decimal precision // -// Example: 1515531081.1234 +// Example: 1515531081.123 func ParseEpochSeconds(value float64) time.Time { - return time.Unix(0, int64(value*float64(time.Second))).UTC() + f := big.NewFloat(value) + f = f.Mul(f, millisecondFloat) + i, _ := f.Int64() + return time.Unix(0, i*1e6).UTC() } // SleepWithContext will wait for the timer duration to expire, or the context diff --git a/time/time_test.go b/time/time_test.go index 533ef0f6d..4b3b698d6 100644 --- a/time/time_test.go +++ b/time/time_test.go @@ -1,6 +1,8 @@ package time import ( + "math" + "strconv" "testing" "time" ) @@ -42,16 +44,50 @@ func TestHTTPDate(t *testing.T) { } func TestEpochSeconds(t *testing.T) { - refTime := time.Date(2018, 1, 9, 20, 51, 21, 123399936, time.UTC) - - epochSeconds := FormatEpochSeconds(refTime) - if e, a := 1515531081.1234, epochSeconds; e != a { - t.Errorf("expected %v, got %v", e, a) + cases := []struct { + reference time.Time + expectedUnix float64 + expectedTime time.Time + }{ + { + reference: time.Date(2018, 1, 9, 20, 51, 21, 123399936, time.UTC), + expectedUnix: 1515531081.123, + expectedTime: time.Date(2018, 1, 9, 20, 51, 21, 1.23e8, time.UTC), + }, + { + reference: time.Date(2018, 1, 9, 20, 51, 21, 1e8, time.UTC), + expectedUnix: 1515531081.1, + expectedTime: time.Date(2018, 1, 9, 20, 51, 21, 1e8, time.UTC), + }, + { + reference: time.Date(2018, 1, 9, 20, 51, 21, 123567891, time.UTC), + expectedUnix: 1515531081.123, + expectedTime: time.Date(2018, 1, 9, 20, 51, 21, 1.23e8, time.UTC), + }, + { + reference: time.Unix(0, math.MaxInt64).UTC(), + expectedUnix: 9223372036.854, + expectedTime: time.Date(2262, 04, 11, 23, 47, 16, 8.54e8, time.UTC), + }, } - parseTime := ParseEpochSeconds(epochSeconds) + for i, tt := range cases { + t.Run(strconv.Itoa(i), func(t *testing.T) { + epochSeconds := FormatEpochSeconds(tt.reference) + if e, a := tt.expectedUnix, epochSeconds; e != a { + t.Errorf("expected %v, got %v", e, a) + } - if e, a := refTime, parseTime; !e.Equal(a) { + parseTime := ParseEpochSeconds(epochSeconds) + + if e, a := tt.expectedTime, parseTime; !e.Equal(a) { + t.Errorf("expected %v, got %v", e, a) + } + }) + } + + // Check an additional edge that higher precision values are truncated to milliseconds + if e, a := time.Date(2018, 1, 9, 20, 51, 21, 1.23e8, time.UTC), ParseEpochSeconds(1515531081.12356); !e.Equal(a) { t.Errorf("expected %v, got %v", e, a) } }