Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tomandersen/timestamp to json #1955

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions dev/src/timestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@
* limitations under the License.
*/

import * as firestore from '@google-cloud/firestore';

import {google} from '../protos/firestore_v1_proto_api';
import {validateInteger} from './validate';
import * as firestore from "@google-cloud/firestore";

Check failure on line 17 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `"@google-cloud/firestore"` with `'@google-cloud/firestore'`

Check warning on line 17 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote

import { google } from "../protos/firestore_v1_proto_api";

Check failure on line 19 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `·google·}·from·"../protos/firestore_v1_proto_api"` with `google}·from·'../protos/firestore_v1_proto_api'`

Check warning on line 19 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote
import { validateInteger } from "./validate";

Check failure on line 20 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `·validateInteger·}·from·"./validate"` with `validateInteger}·from·'./validate'`

Check warning on line 20 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Strings must use singlequote
import api = google.firestore.v1;

/*!
Expand Down Expand Up @@ -216,7 +215,7 @@
*/
toDate(): Date {
return new Date(
this._seconds * 1000 + Math.round(this._nanoseconds / MS_TO_NANOS)
this._seconds * 1000 + Math.floor(this._nanoseconds / MS_TO_NANOS)
);
}

Expand Down Expand Up @@ -308,4 +307,24 @@
const formattedNanoseconds = String(this.nanoseconds).padStart(9, '0');
return formattedSeconds + '.' + formattedNanoseconds;
}

static reviver(this: any, key: string, value: any): any {

Check warning on line 311 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 311 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 311 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
if (key === '') {
const match = value.match(/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d)\.(\d+)([+-][0-2]\d:[0-5]\d|Z)/);

Check failure on line 313 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d)\.(\d+)([+-][0-2]\d:[0-5]\d|Z)/` with `⏎········/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d)\.(\d+)([+-][0-2]\d:[0-5]\d|Z)/⏎······`
return new Timestamp(
Math.floor(Date.parse(match[1] + 'Z') / 1000),
Number(match[2].padEnd(9, '0'))
);
}
}

static replacer(this: any, key: string, value: any): any {

Check warning on line 321 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 321 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 321 in dev/src/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
if (key === '') {
const t: Timestamp = value;
const isoDateSeconds: string = new Date(t._seconds * 1000)
.toISOString()
.split('.')[0];
return `${isoDateSeconds}.${String(t._nanoseconds).padStart(9, '0')}Z`;
}
}
}
17 changes: 17 additions & 0 deletions dev/src/write-batch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,23 @@
this._writeTime.isEqual(other._writeTime))
);
}

static reviver(this: any, key: string, value: any): any {

Check warning on line 100 in dev/src/write-batch.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
if (key === 'writeTime') {
return JSON.parse(value, Timestamp.reviver);
}
}

static replacer(this: any, key: string, value: any): any {
switch (key) {
case '':
return {
writeTime: value._writeTime,
};
case 'writeTime':
return JSON.stringify(value, Timestamp.replacer);
}
}
}

/**
Expand Down
57 changes: 45 additions & 12 deletions dev/test/timestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {describe, it} from 'mocha';
import {expect} from 'chai';
import * as through2 from 'through2';
import { describe, it } from "mocha";

Check failure on line 15 in dev/test/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `·describe,·it·}·from·"mocha"` with `describe,·it}·from·'mocha'`
import { expect } from "chai";

Check failure on line 16 in dev/test/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `·expect·}·from·"chai"` with `expect}·from·'chai'`
import * as through2 from "through2";

Check failure on line 17 in dev/test/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `"through2"` with `'through2'`

import {google} from '../protos/firestore_v1_proto_api';

import * as Firestore from '../src/index';
import {
ApiOverride,
createInstance as createInstanceHelper,
document,
} from '../test/util/helpers';
import { google } from "../protos/firestore_v1_proto_api";

Check failure on line 19 in dev/test/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `·google·}·from·"../protos/firestore_v1_proto_api"` with `google}·from·'../protos/firestore_v1_proto_api'`

import * as Firestore from "../src/index";

Check failure on line 21 in dev/test/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `"../src/index"` with `'../src/index'`
import { ApiOverride, createInstance as createInstanceHelper, document } from "../test/util/helpers";

Check failure on line 22 in dev/test/timestamp.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `·ApiOverride,·createInstance·as·createInstanceHelper,·document·}·from·"../test/util/helpers"` with `⏎··ApiOverride,⏎··createInstance·as·createInstanceHelper,⏎··document,⏎}·from·'../test/util/helpers'`
import api = google.firestore.v1;

function createInstance(opts: {}, document: api.IDocument) {
Expand Down Expand Up @@ -54,7 +49,7 @@
timestampValue: {},
});

describe('timestamps', () => {
describe.only('timestamps', () => {
it('returned by default', () => {
return createInstance({}, DOCUMENT_WITH_TIMESTAMP).then(firestore => {
const expected = new Firestore.Timestamp(-14182920, 123000123);
Expand Down Expand Up @@ -221,4 +216,42 @@
expect(t1 > t2).to.be.false;
expect(t1 >= t2).to.be.false;
});

it('JSON.stringify() on the smallest Timestamp object', () => {
const timestamp = new Firestore.Timestamp(-62135596800, 0);
const writeResult = new Firestore.WriteResult(timestamp);
expect(JSON.stringify(timestamp, Firestore.Timestamp.replacer)).to.equal('"0001-01-01T00:00:00.000000000Z"');
expect(JSON.stringify(writeResult, Firestore.WriteResult.replacer)).to.equal('{"writeTime":"\\"0001-01-01T00:00:00.000000000Z\\""}');
});

it('JSON.parse() on the smallest Timestamp object', () => {
const timestamp = new Firestore.Timestamp(-62135596800, 0);
expect(JSON.parse('"0001-01-01T00:00:00.000000000Z"', Firestore.Timestamp.reviver)).to.deep.equal(timestamp);
});

it('JSON.stringify() on the largest Timestamp object', () => {
const timestamp = new Firestore.Timestamp(253402300799, 999999999);
expect(JSON.parse('"9999-12-31T23:59:59.999999999Z"', Firestore.Timestamp.reviver)).to.deep.equal(timestamp);
});

it('JSON.parse() on the largest Timestamp object', () => {
const timestamp = new Firestore.Timestamp(253402300799, 999999999);
expect(JSON.stringify(timestamp, Firestore.Timestamp.replacer)).to.equal('"9999-12-31T23:59:59.999999999Z"');
});

it('JSON.stringify() on a Timestamp object whose date is in 2023', () => {
const timestamp = new Firestore.Timestamp(1680272000, 840000000);
expect(JSON.parse('"2023-03-31T14:13:20.840000000Z"', Firestore.Timestamp.reviver)).to.deep.equal(timestamp);
});

it('JSON.parse() on a Timestamp object whose date is in 2023', () => {
const timestamp = new Firestore.Timestamp(1680272000, 840000000);
expect(JSON.stringify(timestamp, Firestore.Timestamp.replacer)).to.equal('"2023-03-31T14:13:20.840000000Z"');
});

it.only('JSON.stringify() on the smallest Timestamp object', () => {
const timestamp = new Firestore.Timestamp(-62135596800, 0);
const writeResult = new Firestore.WriteResult(timestamp);
expect(JSON.stringify(writeResult, Firestore.WriteResult.replacer)).to.equal('{"writeTime":"\\"0001-01-01T00:00:00.000000000Z\\""}');
});
});
3 changes: 3 additions & 0 deletions types/firestore.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,9 @@ declare namespace FirebaseFirestore {
export class WriteResult {
private constructor();

static reviver(this: any, key: string, value: any): any;
static replacer(this: any, key: string, value: any): any;

/**
* The write time as set by the Firestore servers.
*/
Expand Down
Loading