From 5eafe6a7bba3ea970b4bdbef6caa260dbe9bf452 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 15 Feb 2021 17:09:35 +0100 Subject: [PATCH 1/5] Test fromRfc3339WithNanoseconds with no fractional part --- packages/tendermint-rpc/src/dates.spec.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/tendermint-rpc/src/dates.spec.ts b/packages/tendermint-rpc/src/dates.spec.ts index dfdf0b94..e1e2a496 100644 --- a/packages/tendermint-rpc/src/dates.spec.ts +++ b/packages/tendermint-rpc/src/dates.spec.ts @@ -5,6 +5,9 @@ import { DateTime, DateWithNanoseconds, fromRfc3339WithNanoseconds, toRfc3339Wit describe("dates", () => { describe("fromRfc3339WithNanoseconds", () => { it("works", () => { + expect(fromRfc3339WithNanoseconds("2020-12-15T10:57:26Z").nanoseconds).toEqual(0); + expect(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7Z").nanoseconds).toEqual(0); + expect(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77Z").nanoseconds).toEqual(0); expect(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.778Z").nanoseconds).toEqual(0); expect(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7789Z").nanoseconds).toEqual(900000); expect(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77809Z").nanoseconds).toEqual(90000); From d610f5cba1c545de2447a1a38dd6fe5b60327670 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 15 Feb 2021 17:16:10 +0100 Subject: [PATCH 2/5] Add toSeconds --- packages/tendermint-rpc/src/dates.spec.ts | 53 ++++++++++++++++++++++- packages/tendermint-rpc/src/dates.ts | 13 ++++++ packages/tendermint-rpc/src/index.ts | 1 + 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/packages/tendermint-rpc/src/dates.spec.ts b/packages/tendermint-rpc/src/dates.spec.ts index e1e2a496..a9883af4 100644 --- a/packages/tendermint-rpc/src/dates.spec.ts +++ b/packages/tendermint-rpc/src/dates.spec.ts @@ -1,6 +1,12 @@ import { ReadonlyDate } from "readonly-date"; -import { DateTime, DateWithNanoseconds, fromRfc3339WithNanoseconds, toRfc3339WithNanoseconds } from "./dates"; +import { + DateTime, + DateWithNanoseconds, + fromRfc3339WithNanoseconds, + toRfc3339WithNanoseconds, + toSeconds, +} from "./dates"; describe("dates", () => { describe("fromRfc3339WithNanoseconds", () => { @@ -55,6 +61,51 @@ describe("dates", () => { }); }); + describe("toSeconds", () => { + it("works", () => { + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26Z"); + expect(toSeconds(date)).toEqual([1608029846, 0]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7Z"); + expect(toSeconds(date)).toEqual([1608029846, 700000000]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77Z"); + expect(toSeconds(date)).toEqual([1608029846, 770000000]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.778Z"); + expect(toSeconds(date)).toEqual([1608029846, 778000000]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7789Z"); + expect(toSeconds(date)).toEqual([1608029846, 778900000]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77809Z"); + expect(toSeconds(date)).toEqual([1608029846, 778090000]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.778009Z"); + expect(toSeconds(date)).toEqual([1608029846, 778009000]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7780009Z"); + expect(toSeconds(date)).toEqual([1608029846, 778000900]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77800009Z"); + expect(toSeconds(date)).toEqual([1608029846, 778000090]); + } + { + const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.778000009Z"); + expect(toSeconds(date)).toEqual([1608029846, 778000009]); + } + }); + }); + describe("DateTime", () => { it("decodes a string", () => { expect(DateTime.decode("2020-12-15T10:57:26.778Z").nanoseconds).toEqual(0); diff --git a/packages/tendermint-rpc/src/dates.ts b/packages/tendermint-rpc/src/dates.ts index 4a15ccfc..c296e1b1 100644 --- a/packages/tendermint-rpc/src/dates.ts +++ b/packages/tendermint-rpc/src/dates.ts @@ -25,6 +25,19 @@ export function toRfc3339WithNanoseconds(dateTime: ReadonlyDateWithNanoseconds): return `${millisecondIso.slice(0, -1)}${nanoseconds.padStart(6, "0")}Z`; } +/** + * Caclulates the UNIX timestamp in seconds as well as the nanoseconds after the given second. + * + * This is useful when dealing with external systems like the protobuf type + * [.google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) + * or any other system that does not use millisecond precision. + */ +export function toSeconds(date: ReadonlyDateWithNanoseconds): [number, number] { + const seconds = Math.floor(date.getTime() / 1000); + const nanos = (date.getTime() % 1000) * 1000000 + (date.nanoseconds ?? 0); + return [seconds, nanos]; +} + /** @deprecated Use fromRfc3339WithNanoseconds/toRfc3339WithNanoseconds instead */ export class DateTime { /** @deprecated Use fromRfc3339WithNanoseconds instead */ diff --git a/packages/tendermint-rpc/src/index.ts b/packages/tendermint-rpc/src/index.ts index c6584a41..5864129f 100644 --- a/packages/tendermint-rpc/src/index.ts +++ b/packages/tendermint-rpc/src/index.ts @@ -6,6 +6,7 @@ export { ReadonlyDateWithNanoseconds, fromRfc3339WithNanoseconds, toRfc3339WithNanoseconds, + toSeconds, } from "./dates"; export { AbciInfoRequest, From 058ce1b1661565af1491de75bff1f4a76fa9ad7c Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Mon, 15 Feb 2021 17:27:14 +0100 Subject: [PATCH 3/5] Add fromSeconds --- packages/tendermint-rpc/src/dates.spec.ts | 57 +++++++++++++++++++++++ packages/tendermint-rpc/src/dates.ts | 11 +++++ packages/tendermint-rpc/src/index.ts | 1 + 3 files changed, 69 insertions(+) diff --git a/packages/tendermint-rpc/src/dates.spec.ts b/packages/tendermint-rpc/src/dates.spec.ts index a9883af4..bacb724c 100644 --- a/packages/tendermint-rpc/src/dates.spec.ts +++ b/packages/tendermint-rpc/src/dates.spec.ts @@ -4,6 +4,7 @@ import { DateTime, DateWithNanoseconds, fromRfc3339WithNanoseconds, + fromSeconds, toRfc3339WithNanoseconds, toSeconds, } from "./dates"; @@ -61,6 +62,62 @@ describe("dates", () => { }); }); + describe("fromSeconds", () => { + it("works", () => { + { + const date = fromSeconds(1608029846); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26Z")); + } + { + const date = fromSeconds(1608029846, 0); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26Z")); + } + { + const date = fromSeconds(1608029846, 1); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.000000001Z")); + } + { + const date = fromSeconds(1608029846, 10); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.000000010Z")); + } + { + const date = fromSeconds(1608029846, 100); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.000000100Z")); + } + { + const date = fromSeconds(1608029846, 1000); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.000001000Z")); + } + { + const date = fromSeconds(1608029846, 10000); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.000010000Z")); + } + { + const date = fromSeconds(1608029846, 100000); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.000100000Z")); + } + { + const date = fromSeconds(1608029846, 1000000); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.001000000Z")); + } + { + const date = fromSeconds(1608029846, 10000000); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.010000000Z")); + } + { + const date = fromSeconds(1608029846, 100000000); + expect(date).toEqual(fromRfc3339WithNanoseconds("2020-12-15T10:57:26.100000000Z")); + } + }); + + it("throws for nanos out of range", () => { + expect(() => fromSeconds(1608029846, 1000000000)).toThrow(); + expect(() => fromSeconds(1608029846, -1)).toThrow(); + expect(() => fromSeconds(1608029846, 1.2)).toThrow(); + expect(() => fromSeconds(1608029846, NaN)).toThrow(); + }); + }); + describe("toSeconds", () => { it("works", () => { { diff --git a/packages/tendermint-rpc/src/dates.ts b/packages/tendermint-rpc/src/dates.ts index c296e1b1..1b4fae84 100644 --- a/packages/tendermint-rpc/src/dates.ts +++ b/packages/tendermint-rpc/src/dates.ts @@ -1,4 +1,5 @@ import { fromRfc3339 } from "@cosmjs/encoding"; +import { Uint32 } from "@cosmjs/math"; import { ReadonlyDate } from "readonly-date"; export interface ReadonlyDateWithNanoseconds extends ReadonlyDate { @@ -25,6 +26,16 @@ export function toRfc3339WithNanoseconds(dateTime: ReadonlyDateWithNanoseconds): return `${millisecondIso.slice(0, -1)}${nanoseconds.padStart(6, "0")}Z`; } +export function fromSeconds(seconds: number, nanos = 0): DateWithNanoseconds { + const checkedNanos = new Uint32(nanos).toNumber(); + if (checkedNanos > 999_999_999) { + throw new Error("Nano seconds must not exceed 999999999"); + } + const out: DateWithNanoseconds = new Date(seconds * 1000 + Math.floor(checkedNanos / 1000000)); + out.nanoseconds = checkedNanos % 1000000; + return out; +} + /** * Caclulates the UNIX timestamp in seconds as well as the nanoseconds after the given second. * diff --git a/packages/tendermint-rpc/src/index.ts b/packages/tendermint-rpc/src/index.ts index 5864129f..1d762ea2 100644 --- a/packages/tendermint-rpc/src/index.ts +++ b/packages/tendermint-rpc/src/index.ts @@ -5,6 +5,7 @@ export { DateTime, ReadonlyDateWithNanoseconds, fromRfc3339WithNanoseconds, + fromSeconds, toRfc3339WithNanoseconds, toSeconds, } from "./dates"; From 470c37bf42375de11467ed5d51f96f447949c199 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 16 Feb 2021 12:07:30 +0100 Subject: [PATCH 4/5] Let toSeconds return an object --- packages/tendermint-rpc/src/dates.spec.ts | 20 ++++++++++---------- packages/tendermint-rpc/src/dates.ts | 9 +++++---- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/packages/tendermint-rpc/src/dates.spec.ts b/packages/tendermint-rpc/src/dates.spec.ts index bacb724c..25862012 100644 --- a/packages/tendermint-rpc/src/dates.spec.ts +++ b/packages/tendermint-rpc/src/dates.spec.ts @@ -122,43 +122,43 @@ describe("dates", () => { it("works", () => { { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26Z"); - expect(toSeconds(date)).toEqual([1608029846, 0]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 0 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7Z"); - expect(toSeconds(date)).toEqual([1608029846, 700000000]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 700000000 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77Z"); - expect(toSeconds(date)).toEqual([1608029846, 770000000]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 770000000 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.778Z"); - expect(toSeconds(date)).toEqual([1608029846, 778000000]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 778000000 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7789Z"); - expect(toSeconds(date)).toEqual([1608029846, 778900000]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 778900000 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77809Z"); - expect(toSeconds(date)).toEqual([1608029846, 778090000]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 778090000 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.778009Z"); - expect(toSeconds(date)).toEqual([1608029846, 778009000]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 778009000 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.7780009Z"); - expect(toSeconds(date)).toEqual([1608029846, 778000900]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 778000900 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.77800009Z"); - expect(toSeconds(date)).toEqual([1608029846, 778000090]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 778000090 }); } { const date = fromRfc3339WithNanoseconds("2020-12-15T10:57:26.778000009Z"); - expect(toSeconds(date)).toEqual([1608029846, 778000009]); + expect(toSeconds(date)).toEqual({ seconds: 1608029846, nanos: 778000009 }); } }); }); diff --git a/packages/tendermint-rpc/src/dates.ts b/packages/tendermint-rpc/src/dates.ts index 1b4fae84..e6206b2e 100644 --- a/packages/tendermint-rpc/src/dates.ts +++ b/packages/tendermint-rpc/src/dates.ts @@ -43,10 +43,11 @@ export function fromSeconds(seconds: number, nanos = 0): DateWithNanoseconds { * [.google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) * or any other system that does not use millisecond precision. */ -export function toSeconds(date: ReadonlyDateWithNanoseconds): [number, number] { - const seconds = Math.floor(date.getTime() / 1000); - const nanos = (date.getTime() % 1000) * 1000000 + (date.nanoseconds ?? 0); - return [seconds, nanos]; +export function toSeconds(date: ReadonlyDateWithNanoseconds): { seconds: number; nanos: number } { + return { + seconds: Math.floor(date.getTime() / 1000), + nanos: (date.getTime() % 1000) * 1000000 + (date.nanoseconds ?? 0), + }; } /** @deprecated Use fromRfc3339WithNanoseconds/toRfc3339WithNanoseconds instead */ From df203fd4f744b665df47fc3dc0762aa06249b375 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Tue, 16 Feb 2021 12:08:04 +0100 Subject: [PATCH 5/5] Fix typo in Caclulates --- packages/tendermint-rpc/src/dates.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tendermint-rpc/src/dates.ts b/packages/tendermint-rpc/src/dates.ts index e6206b2e..fd75d7ea 100644 --- a/packages/tendermint-rpc/src/dates.ts +++ b/packages/tendermint-rpc/src/dates.ts @@ -37,7 +37,7 @@ export function fromSeconds(seconds: number, nanos = 0): DateWithNanoseconds { } /** - * Caclulates the UNIX timestamp in seconds as well as the nanoseconds after the given second. + * Calculates the UNIX timestamp in seconds as well as the nanoseconds after the given second. * * This is useful when dealing with external systems like the protobuf type * [.google.protobuf.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp)