Skip to content

Commit 604acf3

Browse files
authored
Change timestampsInSnapshots default to true. (#1464)
Also update log messages instructing folks what to do if they're using the soon-to-be-removed timestampsInSnapshots setting.
1 parent aa62e43 commit 604acf3

File tree

12 files changed

+75
-69
lines changed

12 files changed

+75
-69
lines changed

packages/firebase/index.d.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -774,22 +774,24 @@ declare namespace firebase.firestore {
774774
ssl?: boolean;
775775

776776
/**
777-
* Enables the use of `Timestamp`s for timestamp fields in
778-
* `DocumentSnapshot`s.
779-
*
780-
* Currently, Firestore returns timestamp fields as `Date` but `Date` only
781-
* supports millisecond precision, which leads to truncation and causes
782-
* unexpected behavior when using a timestamp from a snapshot as a part
783-
* of a subsequent query.
784-
*
785-
* Setting `timestampsInSnapshots` to true will cause Firestore to return
786-
* `Timestamp` values instead of `Date` avoiding this kind of problem. To make
787-
* this work you must also change any code that uses `Date` to use `Timestamp`
788-
* instead.
789-
*
790-
* NOTE: in the future `timestampsInSnapshots: true` will become the
791-
* default and this option will be removed so you should change your code to
792-
* use Timestamp now and opt-in to this new behavior as soon as you can.
777+
* Specifies whether to use `Timestamp` objects for timestamp fields in
778+
* `DocumentSnapshot`s. This is enabled by default and should not be
779+
* disabled.
780+
*
781+
* Previously, Firestore returned timestamp fields as `Date` but `Date`
782+
* only supports millisecond precision, which leads to truncation and
783+
* causes unexpected behavior when using a timestamp from a snapshot as a
784+
* part of a subsequent query.
785+
*
786+
* So now Firestore returns `Timestamp` values instead of `Date`, avoiding
787+
* this kind of problem.
788+
*
789+
* To opt into the old behavior of returning `Date` objects, you can
790+
* temporarily set `timestampsInSnapshots` to false.
791+
*
792+
* @deprecated This setting will be removed in a future release. You should
793+
* update your code to expect `Timestamp` objects and stop using the
794+
* `timestampsInSnapshots` setting.
793795
*/
794796
timestampsInSnapshots?: boolean;
795797

packages/firestore-types/index.d.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,24 @@ export interface Settings {
4444
ssl?: boolean;
4545

4646
/**
47-
* Enables the use of `Timestamp`s for timestamp fields in
48-
* `DocumentSnapshot`s.
47+
* Specifies whether to use `Timestamp` objects for timestamp fields in
48+
* `DocumentSnapshot`s. This is enabled by default and should not be
49+
* disabled.
4950
*
50-
* Currently, Firestore returns timestamp fields as `Date` but `Date` only
51+
* Previously, Firestore returned timestamp fields as `Date` but `Date` only
5152
* supports millisecond precision, which leads to truncation and causes
52-
* unexpected behavior when using a timestamp from a snapshot as a part
53-
* of a subsequent query.
53+
* unexpected behavior when using a timestamp from a snapshot as a part of a
54+
* subsequent query.
5455
*
55-
* Setting `timestampsInSnapshots` to true will cause Firestore to return
56-
* `Timestamp` values instead of `Date` avoiding this kind of problem. To make
57-
* this work you must also change any code that uses `Date` to use `Timestamp`
58-
* instead.
56+
* So now Firestore returns `Timestamp` values instead of `Date`, avoiding
57+
* this kind of problem.
5958
*
60-
* NOTE: in the future `timestampsInSnapshots: true` will become the
61-
* default and this option will be removed so you should change your code to
62-
* use Timestamp now and opt-in to this new behavior as soon as you can.
59+
* To opt into the old behavior of returning `Date` objects, you can
60+
* temporarily set `timestampsInSnapshots` to false.
61+
*
62+
* @deprecated This setting will be removed in a future release. You should
63+
* update your code to expect `Timestamp` objects and stop using the
64+
* `timestampsInSnapshots` setting.
6365
*/
6466
timestampsInSnapshots?: boolean;
6567

packages/firestore/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
# Unreleased
2+
- [changed] The `timestampsInSnapshots` setting is now enabled by default
3+
so timestamp fields read from a `DocumentSnapshot` will be returned as
4+
`Timestamp` objects instead of `Date`. Any code expecting to receive a
5+
`Date` object must be updated.
6+
7+
# 0.9.2
28
- [fixed] Fixed a regression introduced in 5.7.0 that caused apps using
39
experimentalTabSynchronization to hit an exception for "Failed to obtain
410
primary lease for action 'Collect garbage'".
@@ -48,7 +54,7 @@
4854
- [changed] Eliminated superfluous update events for locally cached documents
4955
that are known to lag behind the server version. Instead, we buffer these
5056
events until the client has caught up with the server.
51-
57+
5258
# 0.7.2
5359
- [fixed] Fixed a regression that prevented use of Firestore on ReactNative's
5460
Expo platform (#1138).

packages/firestore/karma.conf.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,11 @@ function getFirestoreSettings(argv) {
6161
return {
6262
host: 'localhost:8080',
6363
ssl: false,
64-
timestampsInSnapshots: true
6564
};
6665
} else {
6766
return {
6867
host: 'firestore.googleapis.com',
6968
ssl: true,
70-
timestampsInSnapshots: true
7169
};
7270
}
7371
}

packages/firestore/src/api/database.ts

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ import {
106106
// settings() defaults:
107107
const DEFAULT_HOST = 'firestore.googleapis.com';
108108
const DEFAULT_SSL = true;
109-
const DEFAULT_TIMESTAMPS_IN_SNAPSHOTS = false;
109+
const DEFAULT_TIMESTAMPS_IN_SNAPSHOTS = true;
110110

111111
/**
112112
* Constant used to indicate the LRU garbage collection should be disabled.
@@ -192,6 +192,37 @@ class FirestoreSettings {
192192
'timestampsInSnapshots',
193193
settings.timestampsInSnapshots
194194
);
195+
196+
// Nobody should set timestampsInSnapshots anymore, but the error depends on
197+
// whether they set it to true or false...
198+
if (settings.timestampsInSnapshots === true) {
199+
log.error(`
200+
The timestampsInSnapshots setting now defaults to true and you no
201+
longer need to explicitly set it. In a future release, the setting
202+
will be removed entirely and so it is recommended that you remove it
203+
from your firestore.settings() call now.`);
204+
} else if (settings.timestampsInSnapshots === false) {
205+
log.error(`
206+
The timestampsInSnapshots setting will soon be removed. YOU MUST UPDATE
207+
YOUR CODE.
208+
209+
To hide this warning, stop using the timestampsInSnapshots setting in your
210+
firestore.settings({ ... }) call.
211+
212+
Once you remove the setting, Timestamps stored in Cloud Firestore will be
213+
read back as Firebase Timestamp objects instead of as system Date objects.
214+
So you will also need to update code expecting a Date to instead expect a
215+
Timestamp. For example:
216+
217+
// Old:
218+
const date = snapshot.get('created_at');
219+
// New:
220+
const timestamp = snapshot.get('created_at'); const date =
221+
timestamp.toDate();
222+
223+
Please audit all existing usages of Date when you enable the new
224+
behavior.`);
225+
}
195226
this.timestampsInSnapshots = objUtils.defaulted(
196227
settings.timestampsInSnapshots,
197228
DEFAULT_TIMESTAMPS_IN_SNAPSHOTS
@@ -373,32 +404,6 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
373404
'FirestoreSettings.host cannot be falsey'
374405
);
375406

376-
if (!this._config.settings.timestampsInSnapshots) {
377-
log.error(`
378-
The behavior for Date objects stored in Firestore is going to change
379-
AND YOUR APP MAY BREAK.
380-
To hide this warning and ensure your app does not break, you need to add the
381-
following code to your app before calling any other Cloud Firestore methods:
382-
383-
const firestore = firebase.firestore();
384-
const settings = {/* your settings... */ timestampsInSnapshots: true};
385-
firestore.settings(settings);
386-
387-
With this change, timestamps stored in Cloud Firestore will be read back as
388-
Firebase Timestamp objects instead of as system Date objects. So you will also
389-
need to update code expecting a Date to instead expect a Timestamp. For example:
390-
391-
// Old:
392-
const date = snapshot.get('created_at');
393-
// New:
394-
const timestamp = snapshot.get('created_at');
395-
const date = timestamp.toDate();
396-
397-
Please audit all existing usages of Date when you enable the new behavior. In a
398-
future release, the behavior will change to the new behavior, so if you do not
399-
follow these steps, YOUR APP MAY BREAK.`);
400-
}
401-
402407
assert(!this._firestoreClient, 'configureClient() called multiple times');
403408

404409
const databaseInfo = new DatabaseInfo(

packages/firestore/src/model/field_value.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ export class TimestampValue extends FieldValue {
329329
}
330330

331331
value(options?: FieldValueOptions): Date | Timestamp {
332-
if (options && options.timestampsInSnapshots) {
332+
if (!options || options.timestampsInSnapshots) {
333333
return this.internalValue;
334334
} else {
335335
return this.internalValue.toDate();

packages/firestore/test/integration/api/fields.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ apiDescribe('Timestamp Fields in snapshots', persistence => {
351351
return { timestamp: ts, nested: { timestamp2: ts } };
352352
};
353353

354-
it('are returned as native dates if timestampsInSnapshots is not set', () => {
354+
it('are returned as native dates if timestampsInSnapshots set to false', () => {
355355
// Avoid the verbose log message triggered by timestampsInSnapshots ==
356356
// false.
357357
const logLevel = log.getLogLevel();
@@ -386,8 +386,6 @@ apiDescribe('Timestamp Fields in snapshots', persistence => {
386386
});
387387

388388
it('are returned as Timestamps', () => {
389-
expect(DEFAULT_SETTINGS['timestampsInSnapshots']).to.equal(true);
390-
391389
const timestamp = new Timestamp(100, 123456000);
392390
// Timestamps are currently truncated to microseconds after being written to
393391
// the database, so a truncated version of the timestamp is needed for

packages/firestore/test/integration/util/helpers.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,11 @@ export const USE_EMULATOR = !!EMULATOR_PORT;
3434
const EMULATOR_FIRESTORE_SETTING = {
3535
host: `localhost:${EMULATOR_PORT}`,
3636
ssl: false,
37-
timestampsInSnapshots: true
3837
};
3938

4039
const PROD_FIRESTORE_SETTING = {
4140
host: 'firestore.googleapis.com',
4241
ssl: true,
43-
timestampsInSnapshots: true
4442
};
4543

4644
export const DEFAULT_SETTINGS = getDefaultSettings();

packages/firestore/test/unit/model/field_value.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ describe('FieldValue', () => {
118118
expect(dateValue1).to.be.an.instanceof(fieldValue.TimestampValue);
119119
expect(dateValue2).to.be.an.instanceof(fieldValue.TimestampValue);
120120

121-
expect(dateValue1.value()).to.deep.equal(date1);
122-
expect(dateValue2.value()).to.deep.equal(date2);
121+
expect(dateValue1.value()).to.deep.equal(Timestamp.fromDate(date1));
122+
expect(dateValue2.value()).to.deep.equal(Timestamp.fromDate(date2));
123123
});
124124

125125
it('can parse geo points', () => {

packages/firestore/test/util/api_helpers.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ export const FIRESTORE = new Firestore({
4747
});
4848

4949
export function firestore(): Firestore {
50-
FIRESTORE.settings({ timestampsInSnapshots: true });
5150
return FIRESTORE;
5251
}
5352

packages/rxfire/test/firestore.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ describe('RxFire Firestore', () => {
8383
beforeEach(() => {
8484
app = initializeApp({ projectId: TEST_PROJECT.projectId });
8585
firestore = app.firestore();
86-
firestore.settings({ timestampsInSnapshots: true });
8786
firestore.disableNetwork();
8887
});
8988

packages/testing/src/api/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ function initializeApp(
132132
app.firestore().settings({
133133
host: FIRESTORE_ADDRESS,
134134
ssl: false,
135-
timestampsInSnapshots: true
136135
});
137136
}
138137
/**

0 commit comments

Comments
 (0)