Skip to content

Commit

Permalink
Extract Date serialisation logic from core
Browse files Browse the repository at this point in the history
  • Loading branch information
zadeviggers committed Oct 8, 2023
1 parent faef377 commit 5255345
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 36 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "miniseed",
"version": "0.1.6",
"version": "0.2.0",
"type": "module",
"scripts": {
"build": "vite build",
Expand Down
14 changes: 13 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,26 @@ Typescript definitions are included.
import {
serialiseToMiniSEEDBuffer,
serialiseToMiniSEEDUint8Array,
startTimeFromDate,
Flags,
} from "miniseed";

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];

const metadata = {
sourceIdentifier: "FDSN:<network>_<station>_...", // An FDSN ID: http://docs.fdsn.org/projects/source-identifiers/
startTime: new Date(), // Or you can manually specify nanoseconds, seconds, etc
// You can manually specify nanoseconds, seconds, etc
startTime: {
year: 1978,
dayOfYear: 264,
hour: 21,
minute: 0,
second: 0, // This needs to be an integer
// There's no milliseconds field - they're included in nanoSecond
nanoSecond: 0,
},
// Or use a helper function to convert from a Date object
startTime: startTimeFromDate(new Date()),
encoding: "Int32", // Or text, Int16, Float32, Float64

// All other metadata fields are optional, but supported.
Expand Down
51 changes: 26 additions & 25 deletions src/miniseed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ export const Flags = {
CLOCK_LOCKED: 0b00100000,
};

type StartTimeData = {
nanoSecond: number;
year: number;
dayOfYear: number;
hour: number;
minute: number;
second: number;
};

type Metadata<T extends keyof typeof encodingTypes> = {
flags?: number;
encoding?: T;
sampleRatePeriod?: number;
dataPublicationVersion?: number;
extraHeaderFields?: any;
sourceIdentifier: string;
startTime:
| Date
| {
nanoSecond: number;
year: number;
dayOfYear: number;
hour: number;
minute: number;
second: number;
};
startTime: StartTimeData;
};

const metadataDefaults = {
Expand All @@ -43,6 +43,22 @@ const metadataDefaults = {
extraHeaderFields: undefined,
};

export function startTimeFromDate(date: Date): StartTimeData {
if (isNaN(date.getTime()))
throw new Error("Invalid Date provided for metadata.timestamp");

return {
year: date.getFullYear(),
dayOfYear: getDayOfYear(date),
hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds(),
// This isn't super precise.
// One day we may get Temporal and all will be well.
nanoSecond: date.getMilliseconds() * 1000000,
};
}

/**
* Serialises an array of numbers to miniSEED v3 format,
* that can then be written to a file.
Expand All @@ -55,21 +71,6 @@ export function serialiseToMiniSEEDBuffer<T extends keyof typeof encodingTypes>(
): ArrayBuffer {
let metadata = { ...metadataDefaults, ..._metadata };

if (metadata.startTime instanceof Date) {
if (isNaN(metadata.startTime.getTime()))
throw new Error("Invalid Date provided for metadata.timestamp");
metadata.startTime = {
year: metadata.startTime.getFullYear(),
dayOfYear: getDayOfYear(metadata.startTime),
hour: metadata.startTime.getHours(),
minute: metadata.startTime.getMinutes(),
second: metadata.startTime.getSeconds(),
// This isn't super precise.
// One day we may get Temporal and all will be well.
nanoSecond: metadata.startTime.getMilliseconds() * 1000000,
};
}

const encodingInfo = encodingTypes[metadata.encoding];

let encodedText: Uint8Array;
Expand Down
39 changes: 39 additions & 0 deletions tests/date-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { describe, it, expect } from "vitest";
import { startTimeFromDate } from "../src/miniseed";

describe("Date utilities", () => {
it("Works with a set date", () => {
const date = new Date("21 September 1978 21:45:30");
const startTime = startTimeFromDate(date);
expect(startTime.year).toEqual(1978);
expect(startTime.dayOfYear).toEqual(264);
expect(startTime.hour).toEqual(21);
expect(startTime.minute).toEqual(45);
expect(startTime.second).toEqual(30);
expect(startTime.nanoSecond).toEqual(0);
});
it("Handles milliseconds correctly", () => {
const date = new Date("21 September 1978");
date.setMilliseconds(500);
const startTime = startTimeFromDate(date);
expect(startTime.nanoSecond).toEqual(500_000_000);
});
it("Handles day-of-year edge cases", () => {
const date1 = new Date("29 February 2016");
const startTime1 = startTimeFromDate(date1);
expect(startTime1.dayOfYear).toEqual(60);

const date2 = new Date("1 March 2016");
const startTime2 = startTimeFromDate(date2);
expect(startTime2.dayOfYear).toEqual(61);
});
it("Handles day-of-year edge cases", () => {
const date1 = new Date("29 February 2016");
const startTime1 = startTimeFromDate(date1);
expect(startTime1.dayOfYear).toEqual(60);

const date2 = new Date("1 March 2016");
const startTime2 = startTimeFromDate(date2);
expect(startTime2.dayOfYear).toEqual(61);
});
});
11 changes: 6 additions & 5 deletions tests/serialise.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ import { describe, it, expect } from "vitest";
import {
serialiseToMiniSEEDBuffer,
serialiseToMiniSEEDUint8Array,
startTimeFromDate,
} from "../src/miniseed";
import jDataView from "z-jdataview-temp-publish";

describe("Size", () => {
it("Works with no data", () => {
const serialised = serialiseToMiniSEEDUint8Array([], {
sourceIdentifier: "",
startTime: new Date(),
startTime: startTimeFromDate(new Date()),
});
expect(serialised.length).toEqual(40);
});
it("Works with complex identifiers", () => {
const serialised = serialiseToMiniSEEDUint8Array([], {
sourceIdentifier: "🔥🦊",
startTime: new Date(),
startTime: startTimeFromDate(new Date()),
});
expect(serialised.length).toEqual(48);
});
Expand Down Expand Up @@ -56,7 +57,7 @@ describe("Size", () => {
],
},
},
startTime: new Date(),
startTime: startTimeFromDate(new Date()),
});
expect(serialised.length).toEqual(517);
});
Expand All @@ -66,7 +67,7 @@ describe("Basic serialisation", () => {
it("Works with basic text", () => {
const serialised = serialiseToMiniSEEDBuffer("beans", {
sourceIdentifier: "",
startTime: new Date(),
startTime: startTimeFromDate(new Date()),
encoding: "text",
}).slice(40);

Expand All @@ -76,7 +77,7 @@ describe("Basic serialisation", () => {
it("Works with basic numbers", () => {
const serialised = serialiseToMiniSEEDBuffer([1, 2, 3, 4, 5], {
sourceIdentifier: "",
startTime: new Date(),
startTime: startTimeFromDate(new Date()),
encoding: "Int32",
}).slice(40);

Expand Down
11 changes: 7 additions & 4 deletions tests/vaid-files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { promisify } from "node:util";
import { writeFile, mkdir, rm } from "node:fs/promises";
import { join } from "node:path";
import { describe, it, expect, beforeAll, afterAll } from "vitest";
import { serialiseToMiniSEEDUint8Array } from "../src/miniseed";
import {
serialiseToMiniSEEDUint8Array,
startTimeFromDate,
} from "../src/miniseed";

const exec = promisify(_exec);

Expand Down Expand Up @@ -49,7 +52,7 @@ describe("Basic data validity", () => {
const data = [1, 2, 3, 4, 5, 6, 7, 8];
const serialised = serialiseToMiniSEEDUint8Array(data, {
sourceIdentifier: "https://zade.viggers.net/example",
startTime: new Date(),
startTime: startTimeFromDate(new Date()),
});
await checkData(serialised, "1-2-3");
});
Expand All @@ -59,7 +62,7 @@ describe("Date validity", () => {
it("Works with a 0 date", async () => {
const serialised = serialiseToMiniSEEDUint8Array([], {
sourceIdentifier: "https://zade.viggers.net/example",
startTime: new Date(0),
startTime: startTimeFromDate(new Date(0)),
});
await checkData(serialised, "date-0-auto");
});
Expand All @@ -80,7 +83,7 @@ describe("Date validity", () => {
it("Works with a new date right now", async () => {
const serialised = serialiseToMiniSEEDUint8Array([], {
sourceIdentifier: "https://zade.viggers.net/example",
startTime: new Date(),
startTime: startTimeFromDate(new Date()),
});
await checkData(serialised, "date-utc");
});
Expand Down

0 comments on commit 5255345

Please sign in to comment.