Skip to content

Commit 9892903

Browse files
authored
Prep for FIRTimestampValue migration to C++ (#3155)
* Clean up GeoPoint port to C++ ... based on things learned porting Timestamps. There's no good way to include conversions equivalent to toGeoPoint in FIRTimestamp, so pull out separate conversion functions that match other similar things. * Extract MakeTimePoint into time_testing.h ... for reuse elsewhere * Add TimestampInternal Hash/Truncate * Use a method similar to NSDate to get current time on apple platforms
1 parent 93307d2 commit 9892903

File tree

15 files changed

+260
-58
lines changed

15 files changed

+260
-58
lines changed

Firestore/Example/Firestore.xcodeproj/project.pbxproj

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@
107107
29FF9029315C3A9FB0E0D79E /* FSTQueryTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E061202154B900B64F25 /* FSTQueryTests.mm */; };
108108
2AAEABFD550255271E3BAC91 /* to_string_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = B68B1E002213A764008977EF /* to_string_apple_test.mm */; };
109109
2B1E95FAFD350C191B525F3B /* empty_credentials_provider_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = AB38D93620239689000A432D /* empty_credentials_provider_test.cc */; };
110+
2D220B9ABFA36CD7AC43D0A7 /* time_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5497CB76229DECDE000FB92F /* time_testing.cc */; };
110111
2E0BBA7E627EB240BA11B0D0 /* exponential_backoff_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = B6D1B68420E2AB1A00B35856 /* exponential_backoff_test.cc */; };
111112
2E169CF1E9E499F054BB873A /* FSTEventAccumulator.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0392021401F00B64F25 /* FSTEventAccumulator.mm */; };
112113
2E6E6164F44B9E3C6BB88313 /* xcgmock_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4425A513895DEC60325A139E /* xcgmock_test.mm */; };
@@ -273,6 +274,9 @@
273274
5493A425225F9990006DE7BA /* status_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5493A423225F9990006DE7BA /* status_apple_test.mm */; };
274275
5493A426225F9990006DE7BA /* status_apple_test.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5493A423225F9990006DE7BA /* status_apple_test.mm */; };
275276
5495EB032040E90200EBA509 /* CodableGeoPointTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5495EB022040E90200EBA509 /* CodableGeoPointTests.swift */; };
277+
5497CB77229DECDE000FB92F /* time_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5497CB76229DECDE000FB92F /* time_testing.cc */; };
278+
5497CB78229DECDE000FB92F /* time_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5497CB76229DECDE000FB92F /* time_testing.cc */; };
279+
5497CB79229DECDE000FB92F /* time_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5497CB76229DECDE000FB92F /* time_testing.cc */; };
276280
54995F6F205B6E12004EFFA0 /* leveldb_key_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54995F6E205B6E12004EFFA0 /* leveldb_key_test.cc */; };
277281
549CCA5020A36DBC00BCEB75 /* sorted_set_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA4C20A36DBB00BCEB75 /* sorted_set_test.cc */; };
278282
549CCA5120A36DBC00BCEB75 /* tree_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA4D20A36DBB00BCEB75 /* tree_sorted_map_test.cc */; };
@@ -371,6 +375,7 @@
371375
61F72C5620BC48FD001A68CB /* serializer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 61F72C5520BC48FD001A68CB /* serializer_test.cc */; };
372376
627253FDEC6BB5549FE77F4E /* tree_sorted_map_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 549CCA4D20A36DBB00BCEB75 /* tree_sorted_map_test.cc */; };
373377
62DA31B79FE97A90EEF28B0B /* delayed_constructor_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = D0A6E9136804A41CEC9D55D4 /* delayed_constructor_test.cc */; };
378+
6300709ECDE8E0B5A8645F8D /* time_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5497CB76229DECDE000FB92F /* time_testing.cc */; };
374379
63BB61B6366E7F80C348419D /* FSTLevelDBTransactionTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 132E36BB104830BD806351AC /* FSTLevelDBTransactionTests.mm */; };
375380
660E99DEDA0A6FC1CCB200F9 /* FIRArrayTransformTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 73866A9F2082B069009BB4FF /* FIRArrayTransformTests.mm */; };
376381
6672B445E006A7708B8531ED /* FSTImmutableSortedDictionary+Testing.m in Sources */ = {isa = PBXBuildFile; fileRef = DE2EF0801F3D0B6E003D0CDC /* FSTImmutableSortedDictionary+Testing.m */; };
@@ -468,6 +473,7 @@
468473
9D71628E38D9F64C965DF29E /* FSTAPIHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E04E202154AA00B64F25 /* FSTAPIHelpers.mm */; };
469474
A17DBC8F24127DA8A381F865 /* testutil.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54A0352820A3B3BD003E0143 /* testutil.cc */; };
470475
A1F57CC739211F64F2E9232D /* hard_assert_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */; };
476+
A25FF76DEF542E01A2DF3B0E /* time_testing.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5497CB76229DECDE000FB92F /* time_testing.cc */; };
471477
A21819C437C3C80450D7EEEE /* writer_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = BC3C788D290A935C353CEAA1 /* writer_test.cc */; };
472478
A38F4AE525A87FDEA41DED47 /* FSTLevelDBQueryCacheTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E0982021552C00B64F25 /* FSTLevelDBQueryCacheTests.mm */; };
473479
A4ECA8335000CBDF94586C94 /* FSTDatastoreTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5492E07E202154EC00B64F25 /* FSTDatastoreTests.mm */; };
@@ -775,7 +781,8 @@
775781
4425A513895DEC60325A139E /* xcgmock_test.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = xcgmock_test.mm; sourceTree = "<group>"; };
776782
444B7AB3F5A2929070CB1363 /* hard_assert_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; path = hard_assert_test.cc; sourceTree = "<group>"; };
777783
4C73C0CC6F62A90D8573F383 /* string_apple_benchmark.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = string_apple_benchmark.mm; sourceTree = "<group>"; };
778-
5342CDDB137B4E93E2E85CCA /* byte_string_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; name = byte_string_test.cc; path = nanopb/byte_string_test.cc; sourceTree = "<group>"; };
784+
5342CDDB137B4E93E2E85CCA /* byte_string_test.cc */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.cpp; name = byte_string_test.cc; path = nanopb/byte_string_test.cc; sourceTree = "<group>"; };
785+
535B1420A19BEAA7FA4D77C8 /* ordered_code_benchmark.mm */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.cpp.objcpp; path = ordered_code_benchmark.mm; sourceTree = "<group>"; };
779786
54131E9620ADE678001DF3FF /* string_format_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = string_format_test.cc; sourceTree = "<group>"; };
780787
544129D021C2DDC800EFB9CC /* query.pb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = query.pb.h; sourceTree = "<group>"; };
781788
544129D121C2DDC800EFB9CC /* common.pb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.pb.h; sourceTree = "<group>"; };
@@ -865,6 +872,8 @@
865872
5492E0C32021557E00B64F25 /* FSTRemoteEventTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTRemoteEventTests.mm; sourceTree = "<group>"; };
866873
5493A423225F9990006DE7BA /* status_apple_test.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = status_apple_test.mm; sourceTree = "<group>"; };
867874
5495EB022040E90200EBA509 /* CodableGeoPointTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodableGeoPointTests.swift; sourceTree = "<group>"; };
875+
5497CB75229DECDE000FB92F /* time_testing.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = time_testing.h; sourceTree = "<group>"; };
876+
5497CB76229DECDE000FB92F /* time_testing.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = time_testing.cc; sourceTree = "<group>"; };
868877
54995F6E205B6E12004EFFA0 /* leveldb_key_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = leveldb_key_test.cc; sourceTree = "<group>"; };
869878
549CCA4C20A36DBB00BCEB75 /* sorted_set_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sorted_set_test.cc; sourceTree = "<group>"; };
870879
549CCA4D20A36DBB00BCEB75 /* tree_sorted_map_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tree_sorted_map_test.cc; sourceTree = "<group>"; };
@@ -1237,6 +1246,8 @@
12371246
CD422AF3E4515FB8E9BE67A0 /* equals_tester.h */,
12381247
54A0352820A3B3BD003E0143 /* testutil.cc */,
12391248
54A0352920A3B3BD003E0143 /* testutil.h */,
1249+
5497CB76229DECDE000FB92F /* time_testing.cc */,
1250+
5497CB75229DECDE000FB92F /* time_testing.h */,
12401251
BA6E5B9D53CCF301F58A62D7 /* xcgmock.h */,
12411252
4425A513895DEC60325A139E /* xcgmock_test.mm */,
12421253
);
@@ -3130,6 +3141,7 @@
31303141
4A3FF3B16A39A5DC6B7EBA51 /* target.pb.cc in Sources */,
31313142
E764F0F389E7119220EB212C /* target_id_generator_test.cc in Sources */,
31323143
32A95242C56A1A230231DB6A /* testutil.cc in Sources */,
3144+
5497CB78229DECDE000FB92F /* time_testing.cc in Sources */,
31333145
ACC9369843F5ED3BD2284078 /* timestamp_test.cc in Sources */,
31343146
2AAEABFD550255271E3BAC91 /* to_string_apple_test.mm in Sources */,
31353147
1E2AE064CF32A604DC7BFD4D /* to_string_test.cc in Sources */,
@@ -3306,6 +3318,7 @@
33063318
81B23D2D4E061074958AF12F /* target.pb.cc in Sources */,
33073319
DA4303684707606318E1914D /* target_id_generator_test.cc in Sources */,
33083320
8388418F43042605FB9BFB92 /* testutil.cc in Sources */,
3321+
5497CB79229DECDE000FB92F /* time_testing.cc in Sources */,
33093322
26CB3D7C871BC56456C6021E /* timestamp_test.cc in Sources */,
33103323
5BE49546D57C43DDFCDB6FBD /* to_string_apple_test.mm in Sources */,
33113324
E500AB82DF2E7F3AFDB1AB3F /* to_string_test.cc in Sources */,
@@ -3345,6 +3358,7 @@
33453358
4D42E5C756229C08560DD731 /* XCTestCase+Await.mm in Sources */,
33463359
7B8D7BAC1A075DB773230505 /* app_testing.mm in Sources */,
33473360
409C0F2BFC2E1BECFFAC4D32 /* testutil.cc in Sources */,
3361+
6300709ECDE8E0B5A8645F8D /* time_testing.cc in Sources */,
33483362
1EF47EF3D03B0847007C2318 /* xcgmock_test.mm in Sources */,
33493363
);
33503364
runOnlyForDeploymentPostprocessing = 0;
@@ -3374,6 +3388,7 @@
33743388
736C4E82689F1CA1859C4A3F /* XCTestCase+Await.mm in Sources */,
33753389
8F4F40E9BC7ED588F67734D5 /* app_testing.mm in Sources */,
33763390
A17DBC8F24127DA8A381F865 /* testutil.cc in Sources */,
3391+
A25FF76DEF542E01A2DF3B0E /* time_testing.cc in Sources */,
33773392
A94884460990CD48CC0AD070 /* xcgmock_test.mm in Sources */,
33783393
);
33793394
runOnlyForDeploymentPostprocessing = 0;
@@ -3557,6 +3572,7 @@
35573572
618BBEA620B89AAC00B5BCE7 /* target.pb.cc in Sources */,
35583573
AB380CFB2019388600D97691 /* target_id_generator_test.cc in Sources */,
35593574
54A0352A20A3B3BD003E0143 /* testutil.cc in Sources */,
3575+
5497CB77229DECDE000FB92F /* time_testing.cc in Sources */,
35603576
ABF6506C201131F8005F2C74 /* timestamp_test.cc in Sources */,
35613577
B68B1E012213A765008977EF /* to_string_apple_test.mm in Sources */,
35623578
B696858E2214B53900271095 /* to_string_test.cc in Sources */,
@@ -3615,6 +3631,7 @@
36153631
5492E0442021457E00B64F25 /* XCTestCase+Await.mm in Sources */,
36163632
EBFC611B1BF195D0EC710AF4 /* app_testing.mm in Sources */,
36173633
CA989C0E6020C372A62B7062 /* testutil.cc in Sources */,
3634+
2D220B9ABFA36CD7AC43D0A7 /* time_testing.cc in Sources */,
36183635
4D1F46B2DD91198C8867C04C /* xcgmock_test.mm in Sources */,
36193636
);
36203637
runOnlyForDeploymentPostprocessing = 0;

Firestore/core/include/firebase/firestore/timestamp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Timestamp {
4646
* Creates a new timestamp representing the epoch (with seconds and
4747
* nanoseconds set to 0).
4848
*/
49-
Timestamp();
49+
Timestamp() = default;
5050

5151
/**
5252
* Creates a new timestamp.

Firestore/core/src/firebase/firestore/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ cc_library(
1818
SOURCES
1919
geo_point.cc
2020
timestamp.cc
21+
timestamp_internal.cc
2122
timestamp_internal.h
2223
DEPENDS
2324
firebase_firestore_util

Firestore/core/src/firebase/firestore/model/field_value.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <vector>
2626

2727
#include "Firestore/core/src/firebase/firestore/immutable/sorted_map.h"
28+
#include "Firestore/core/src/firebase/firestore/timestamp_internal.h"
2829
#include "Firestore/core/src/firebase/firestore/util/comparison.h"
2930
#include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
3031
#include "Firestore/core/src/firebase/firestore/util/hashing.h"
@@ -241,7 +242,7 @@ class TimestampValue : public BaseValue {
241242
}
242243

243244
size_t Hash() const override {
244-
return util::Hash(value().seconds(), value().nanoseconds());
245+
return TimestampInternal::Hash(value());
245246
}
246247

247248
const Timestamp& value() const {
@@ -293,9 +294,7 @@ class ServerTimestampValue : public FieldValue::BaseValue {
293294
}
294295

295296
size_t Hash() const override {
296-
size_t result = util::Hash(local_write_time_.seconds(),
297-
local_write_time_.nanoseconds());
298-
297+
size_t result = TimestampInternal::Hash(local_write_time_);
299298
if (previous_value_) {
300299
result = util::Hash(result, *previous_value_);
301300
}

Firestore/core/src/firebase/firestore/timestamp.cc

Lines changed: 59 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,84 @@
1818

1919
#include <ostream>
2020

21+
#if defined(__APPLE__)
22+
#import <CoreFoundation/CoreFoundation.h>
23+
#elif defined(_STLPORT_VERSION)
24+
#include <ctime>
25+
#endif
26+
2127
#include "Firestore/core/src/firebase/firestore/util/hard_assert.h"
2228
#include "absl/strings/str_cat.h"
2329

2430
namespace firebase {
2531

26-
Timestamp::Timestamp() {
32+
namespace {
33+
34+
// We pass it by value without std::move.
35+
static_assert(std::is_trivially_copyable<Timestamp>::value,
36+
"Timestamp must be trivially copyable");
37+
38+
constexpr int32_t kNanosPerSecond = 1E9;
39+
40+
/**
41+
* Creates a `Timestamp` from the given non-normalized inputs.
42+
*
43+
* Timestamp protos require `Timestamp` to always has a positive number of
44+
* nanoseconds that is counting forward. For negative time, we need to adjust
45+
* representations with negative nanoseconds. That is, make (negative seconds s1
46+
* + negative nanoseconds ns1) into (negative seconds s2 + positive nanoseconds
47+
* ns2). Since nanosecond part is always less than 1 second in our
48+
* representation, instead of starting at s1 and going back ns1 nanoseconds,
49+
* start at (s1 minus one second) and go *forward* ns2 = (1 second + ns1, ns1 <
50+
* 0) nanoseconds.
51+
*/
52+
Timestamp MakeNormalizedTimestamp(int64_t seconds, int64_t nanos) {
53+
if (nanos < 0) {
54+
// Note: if nanoseconds are negative, it must mean that seconds are
55+
// non-positive, but the formula would still be valid, so no need to check.
56+
seconds = seconds - 1;
57+
nanos = kNanosPerSecond + nanos;
58+
}
59+
60+
HARD_ASSERT(nanos < kNanosPerSecond);
61+
62+
return {seconds, static_cast<int32_t>(nanos)};
2763
}
2864

65+
} // namespace
66+
2967
Timestamp::Timestamp(const int64_t seconds, const int32_t nanoseconds)
3068
: seconds_(seconds), nanoseconds_(nanoseconds) {
3169
ValidateBounds();
3270
}
3371

3472
Timestamp Timestamp::Now() {
35-
#if !defined(_STLPORT_VERSION)
73+
#if defined(__APPLE__)
74+
// Originally, FIRTimestamp used NSDate to get current time. This method
75+
// preserves the lower accuracy of that method.
76+
CFAbsoluteTime now =
77+
CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
78+
double seconds_double;
79+
double fraction = modf(now, &seconds_double);
80+
auto seconds = static_cast<int64_t>(seconds_double);
81+
auto nanos = static_cast<int32_t>(fraction * kNanosPerSecond);
82+
return MakeNormalizedTimestamp(seconds, nanos);
83+
84+
#elif !defined(_STLPORT_VERSION)
3685
// Use the standard <chrono> library from C++11 if possible.
3786
return FromTimePoint(std::chrono::system_clock::now());
3887
#else
39-
// If <chrono> is unavailable, use clock_gettime from POSIX, which supports up
40-
// to nanosecond resolution. Note that it's a non-standard function contained
41-
// in <time.h>.
88+
// If <chrono> is unavailable, use clock_gettime from POSIX, which supports
89+
// up to nanosecond resolution. Note that it's a non-standard function
90+
// contained in <time.h>.
4291
//
4392
// Note: it's possible to check for availability of POSIX clock_gettime using
4493
// macros (see "Availability" at https://linux.die.net/man/3/clock_gettime).
4594
// However, the only platform where <chrono> isn't available is Android with
4695
// STLPort standard library, where clock_gettime is known to be available.
4796
timespec now;
4897
clock_gettime(CLOCK_REALTIME, &now);
49-
return Timestamp(now.tv_sec, now.tv_nsec);
98+
return MakeNormalizedTimestamp(now.tv_sec, now.tv_nsec);
5099
#endif // !defined(_STLPORT_VERSION)
51100
}
52101

@@ -60,26 +109,9 @@ Timestamp Timestamp::FromTimePoint(
60109
namespace chr = std::chrono;
61110
const auto epoch_time = time_point.time_since_epoch();
62111
auto seconds = chr::duration_cast<chr::duration<int64_t>>(epoch_time);
63-
auto nanoseconds = chr::duration_cast<chr::nanoseconds>(epoch_time - seconds);
64-
HARD_ASSERT(nanoseconds.count() < 1 * 1000 * 1000 * 1000);
65-
66-
if (nanoseconds.count() < 0) {
67-
// Timestamp format always has a positive number of nanoseconds that is
68-
// counting forward. For negative time, we need to transform chrono
69-
// representation of (negative seconds s1 + negative nanoseconds ns1) to
70-
// (negative seconds s2 + positive nanoseconds ns2). Since nanosecond part
71-
// is always less than 1 second in our representation, instead of starting
72-
// at s1 and going back ns1 nanoseconds, start at (s1 minus one second) and
73-
// go *forward* ns2 = (1 second + ns1, ns1 < 0) nanoseconds.
74-
//
75-
// Note: if nanoseconds are negative, it must mean that seconds are
76-
// non-positive, but the formula would still be valid, so no need to check.
77-
seconds = seconds - chr::seconds(1);
78-
nanoseconds = chr::seconds(1) + nanoseconds;
79-
}
112+
auto nanos = chr::duration_cast<chr::nanoseconds>(epoch_time - seconds);
80113

81-
const Timestamp result{seconds.count(),
82-
static_cast<int32_t>(nanoseconds.count())};
114+
Timestamp result = MakeNormalizedTimestamp(seconds.count(), nanos.count());
83115
result.ValidateBounds();
84116
return result;
85117
}
@@ -98,8 +130,8 @@ std::ostream& operator<<(std::ostream& out, const Timestamp& timestamp) {
98130
void Timestamp::ValidateBounds() const {
99131
HARD_ASSERT(nanoseconds_ >= 0, "Timestamp nanoseconds out of range: %s",
100132
nanoseconds_);
101-
HARD_ASSERT(nanoseconds_ < 1e9, "Timestamp nanoseconds out of range: %s",
102-
nanoseconds_);
133+
HARD_ASSERT(nanoseconds_ < kNanosPerSecond,
134+
"Timestamp nanoseconds out of range: %s", nanoseconds_);
103135
// Midnight at the beginning of 1/1/1 is the earliest timestamp Firestore
104136
// supports.
105137
HARD_ASSERT(seconds_ >= -62135596800L, "Timestamp seconds out of range: %s",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright 2019 Google
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "Firestore/core/src/firebase/firestore/timestamp_internal.h"
18+
19+
#include "Firestore/core/src/firebase/firestore/util/hashing.h"
20+
21+
namespace util = firebase::firestore::util;
22+
23+
namespace firebase {
24+
25+
size_t TimestampInternal::Hash(const Timestamp& timestamp) {
26+
return util::Hash(timestamp.seconds(), timestamp.nanoseconds());
27+
}
28+
29+
Timestamp TimestampInternal::Truncate(const Timestamp& timestamp) {
30+
int32_t truncated_nanos = timestamp.nanoseconds() / 1000 * 1000;
31+
return Timestamp(timestamp.seconds(), truncated_nanos);
32+
}
33+
34+
} // namespace firebase

Firestore/core/src/firebase/firestore/timestamp_internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ class TimestampInternal {
4242
static firebase::Timestamp Min() {
4343
return {-62135596800L, 0};
4444
}
45+
46+
static size_t Hash(const Timestamp& timestamp);
47+
48+
/**
49+
* Truncates the input timestamp to microsecond precision to match backend
50+
* behavior.
51+
*/
52+
static Timestamp Truncate(const Timestamp& timestamp);
4553
};
4654

4755
} // namespace firebase

Firestore/core/test/firebase/firestore/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,6 @@ cc_test(
1818
geo_point_test.cc
1919
timestamp_test.cc
2020
DEPENDS
21+
absl_time
2122
firebase_firestore_types
2223
)

0 commit comments

Comments
 (0)