Skip to content

Commit f8480f1

Browse files
author
Divjot Arora
committed
GODRIVER-1688 Remove UnixNano call from NewDateTimeFromTime (#463)
1 parent 522c498 commit f8480f1

File tree

5 files changed

+26
-4
lines changed

5 files changed

+26
-4
lines changed

bson/bsoncodec/default_value_encoders.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ func (dve DefaultValueEncoders) TimeEncodeValue(ec EncodeContext, vw bsonrw.Valu
252252
return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val}
253253
}
254254
tt := val.Interface().(time.Time)
255-
return vw.WriteDateTime(tt.Unix()*1000 + int64(tt.Nanosecond()/1e6))
255+
dt := primitive.NewDateTimeFromTime(tt)
256+
return vw.WriteDateTime(int64(dt))
256257
}
257258

258259
// ByteSliceEncodeValue is the ValueEncoderFunc for []byte.

bson/bsoncodec/time_codec.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"go.mongodb.org/mongo-driver/bson/bsonoptions"
1515
"go.mongodb.org/mongo-driver/bson/bsonrw"
1616
"go.mongodb.org/mongo-driver/bson/bsontype"
17+
"go.mongodb.org/mongo-driver/bson/primitive"
1718
)
1819

1920
const (
@@ -97,5 +98,6 @@ func (tc *TimeCodec) EncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val re
9798
return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val}
9899
}
99100
tt := val.Interface().(time.Time)
100-
return vw.WriteDateTime(tt.Unix()*1000 + int64(tt.Nanosecond()/1e6))
101+
dt := primitive.NewDateTimeFromTime(tt)
102+
return vw.WriteDateTime(int64(dt))
101103
}

bson/bsonrw/extjson_wrappers.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ func parseDatetimeString(data string) (int64, error) {
217217
return 0, fmt.Errorf("invalid $date value string: %s", data)
218218
}
219219

220-
return t.Unix()*1e3 + int64(t.Nanosecond())/1e6, nil
220+
return int64(primitive.NewDateTimeFromTime(t)), nil
221221
}
222222

223223
func parseDatetimeObject(data *extJSONObject) (d int64, err error) {

bson/primitive/primitive.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (d DateTime) Time() time.Time {
5252

5353
// NewDateTimeFromTime creates a new DateTime from a Time.
5454
func NewDateTimeFromTime(t time.Time) DateTime {
55-
return DateTime(t.UnixNano() / 1000000)
55+
return DateTime(t.Unix()*1e3 + int64(t.Nanosecond())/1e6)
5656
}
5757

5858
// Null represents the BSON null value.

bson/primitive/primitive_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ package primitive
88

99
import (
1010
"testing"
11+
"time"
1112

1213
"github.com/stretchr/testify/require"
14+
"go.mongodb.org/mongo-driver/internal/testutil/assert"
1315
)
1416

1517
// The same interface as bsoncodec.Zeroer implemented for tests.
@@ -78,3 +80,20 @@ func TestRegexCompare(t *testing.T) {
7880
})
7981
}
8082
}
83+
84+
func TestDateTime(t *testing.T) {
85+
t.Run("NewDateTimeFromTime", func(t *testing.T) {
86+
t.Run("range is not limited", func(t *testing.T) {
87+
// If the implementation internally calls time.Time.UnixNano(), the constructor cannot handle times after
88+
// the year 2262.
89+
90+
timeFormat := "2006-01-02T15:04:05.999Z07:00"
91+
timeString := "3001-01-01T00:00:00Z"
92+
tt, err := time.Parse(timeFormat, timeString)
93+
assert.Nil(t, err, "Parse error: %v", err)
94+
95+
dt := NewDateTimeFromTime(tt)
96+
assert.True(t, dt > 0, "expected a valid DateTime greater than 0, got %v", dt)
97+
})
98+
})
99+
}

0 commit comments

Comments
 (0)