Skip to content

Commit

Permalink
Added helper function to create a DWN compatible timestamp (#583)
Browse files Browse the repository at this point in the history
  • Loading branch information
flothjl committed Oct 30, 2023
1 parent e404dec commit c0f2a95
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export { Protocols } from './utils/protocols.js';
export { ProtocolsConfigure, ProtocolsConfigureOptions } from './interfaces/protocols-configure.js';
export { ProtocolsQuery, ProtocolsQueryOptions } from './interfaces/protocols-query.js';
export { Records } from './utils/records.js';
export { createTimestamp } from './utils/time.js';
export { RecordsDelete, RecordsDeleteOptions } from './interfaces/records-delete.js';
export { RecordsRead, RecordsReadOptions } from './interfaces/records-read.js';
export { Secp256k1 } from './utils/secp256k1.js';
Expand Down
24 changes: 23 additions & 1 deletion src/utils/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,28 @@ export function getCurrentTimeInHighPrecision(): string {
return Temporal.Now.instant().toString({ smallestUnit: 'microseconds' });
}

/**
* Creates a UTC ISO-8601 timestamp in microsecond precision accepted by DWN.
* @param options - Options for creating the timestamp.
* @returns string
*/
export function createTimestamp(
options: {year?: number, month?: number, day?: number, hour?: number, minute?: number, second?: number, millisecond?: number, microsecond?: number}
): string {
const { year, month, day, hour, minute, second, millisecond, microsecond } = options;
return Temporal.ZonedDateTime.from({
timeZone: 'UTC',
year,
month,
day,
hour,
minute,
second,
millisecond,
microsecond
}).toInstant().toString({ smallestUnit: 'microseconds' });
}

/**
* We must sleep for at least 2ms to avoid timestamp collisions during testing.
* https://github.com/TBD54566975/dwn-sdk-js/issues/481
Expand All @@ -35,6 +57,6 @@ export function validateTimestamp(timestamp: string): void {
try {
Temporal.Instant.from(timestamp);
} catch {
throw new DwnError(DwnErrorCode.TimestampInvalid,`Invalid timestamp: ${timestamp}`);
throw new DwnError(DwnErrorCode.TimestampInvalid, `Invalid timestamp: ${timestamp}`);
}
}
18 changes: 9 additions & 9 deletions tests/utils/test-data-generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import type { PrivateJwk, PublicJwk } from '../../src/types/jose-types.js';

import * as cbor from '@ipld/dag-cbor';
import { CID } from 'multiformats/cid';
import { createTimestamp } from '../../src/index.js';
import { DataStream } from '../../src/utils/data-stream.js';
import { getCurrentTimeInHighPrecision } from '../../src/utils/time.js';
import { PermissionsGrant } from '../../src/interfaces/permissions-grant.js';
Expand Down Expand Up @@ -832,15 +833,14 @@ export class TestDataGenerator {
* @returns random UTC ISO-8601 timestamp
*/
public static randomTimestamp(): string {
return Temporal.ZonedDateTime.from({
timeZone : 'UTC',
year : this.randomInt(2000, 2022),
month : this.randomInt(1, 12),
day : this.randomInt(1, 28),
hour : this.randomInt(0, 23),
minute : this.randomInt(0, 59),
second : this.randomInt(0, 59),
}).toInstant().toString({ smallestUnit: 'microseconds' });
return createTimestamp({
year : this.randomInt(2000, 2022),
month : this.randomInt(1, 12),
day : this.randomInt(1, 28),
hour : this.randomInt(0, 23),
minute : this.randomInt(0, 59),
second : this.randomInt(0, 59),
});
}

/**
Expand Down
33 changes: 32 additions & 1 deletion tests/utils/time.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DwnErrorCode } from '../../src/core/dwn-error.js';
import { expect } from 'chai';
import { TestDataGenerator } from '../utils/test-data-generator.js';
import { validateTimestamp } from '../../src/utils/time.js';
import { createTimestamp, validateTimestamp } from '../../src/utils/time.js';


describe('time', () => {
Expand All @@ -26,4 +26,35 @@ describe('time', () => {
});
});
});

describe('createTimestamp', () => {
it('should create a valid timestamp', () => {
const timestamp = createTimestamp({
year : 2022,
month : 4,
day : 29,
hour : 10,
minute : 30,
second : 0,
millisecond : 123,
microsecond : 456
});
expect(timestamp).to.equal('2022-04-29T10:30:00.123456Z');
});

for (let i = 0; i < 5; i++) {
const year = TestDataGenerator.randomInt(1900, 2500);
const month = TestDataGenerator.randomInt(1, 12);
const day = TestDataGenerator.randomInt(1, 28);
const hour = TestDataGenerator.randomInt(0, 23);
const minute = TestDataGenerator.randomInt(0, 59);
const second = TestDataGenerator.randomInt(0, 59);
const millisecond = TestDataGenerator.randomInt(0, 999);
const microsecond = TestDataGenerator.randomInt(0, 999);
it(`should create a valid timestamp for random values ${i}`, () => {
const timestamp = createTimestamp({ year, month, day, hour, minute, second, millisecond, microsecond });
expect(()=> validateTimestamp(timestamp)).to.not.throw();
});
}
});
});

0 comments on commit c0f2a95

Please sign in to comment.