Skip to content

Commit 7fc391c

Browse files
authored
feat(scalars): Timestamp, float64, int64 (#35)
Co-authored-by: Kemal Hadimli <disq@users.noreply.github.com>
1 parent c14f017 commit 7fc391c

File tree

5 files changed

+221
-0
lines changed

5 files changed

+221
-0
lines changed

package-lock.json

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@
8181
"dependencies": {
8282
"@apache-arrow/esnext-esm": "^12.0.1",
8383
"@cloudquery/plugin-pb-javascript": "^0.0.7",
84+
"@types/luxon": "^3.3.1",
8485
"boolean": "^3.2.0",
86+
"luxon": "^3.4.0",
8587
"winston": "^3.10.0",
8688
"yargs": "^17.7.2"
8789
}

src/scalar/float64.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { DataType, Float64 as ArrowFloat64 } from '@apache-arrow/esnext-esm';
2+
3+
import { Scalar } from './scalar.js';
4+
import { isInvalid, NULL_VALUE } from './util.js';
5+
6+
export class Float64 implements Scalar<number> {
7+
private _valid = false;
8+
private _value: number = 0;
9+
10+
public constructor(v: unknown) {
11+
this.value = v;
12+
return this;
13+
}
14+
15+
public get dataType(): DataType {
16+
return new ArrowFloat64();
17+
}
18+
19+
public get valid(): boolean {
20+
return this._valid;
21+
}
22+
23+
public get value(): number {
24+
return this._value;
25+
}
26+
27+
public set value(value: unknown) {
28+
if (isInvalid(value)) {
29+
this._valid = false;
30+
return;
31+
}
32+
33+
if (value instanceof Float64) {
34+
this._valid = value.valid;
35+
this._value = value.value;
36+
return;
37+
}
38+
39+
if (typeof value === 'number') {
40+
this._value = value;
41+
this._valid = true;
42+
return;
43+
}
44+
45+
const floatValue = Number.parseFloat(String(value));
46+
if (!Number.isNaN(floatValue)) {
47+
this._value = floatValue;
48+
this._valid = true;
49+
return;
50+
}
51+
52+
throw new Error(`Unable to set '${value}' as Float64`);
53+
}
54+
55+
public toString() {
56+
if (this._valid) {
57+
return String(this._value);
58+
}
59+
60+
return NULL_VALUE;
61+
}
62+
}

src/scalar/int64.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { DataType, Int64 as ArrowInt64 } from '@apache-arrow/esnext-esm';
2+
3+
import { Scalar } from './scalar.js';
4+
import { isInvalid, NULL_VALUE } from './util.js';
5+
6+
export class Int64 implements Scalar<bigint> {
7+
private _valid = false;
8+
private _value: bigint = BigInt(0);
9+
10+
public constructor(v: unknown) {
11+
this.value = v;
12+
return this;
13+
}
14+
15+
public get dataType(): DataType {
16+
return new ArrowInt64();
17+
}
18+
19+
public get valid(): boolean {
20+
return this._valid;
21+
}
22+
23+
public get value(): bigint {
24+
return this._value;
25+
}
26+
27+
public set value(value: unknown) {
28+
if (isInvalid(value)) {
29+
this._valid = false;
30+
return;
31+
}
32+
33+
if (value instanceof Int64) {
34+
this._valid = value.valid;
35+
this._value = value.value;
36+
return;
37+
}
38+
39+
if (typeof value === 'bigint') {
40+
this._value = value;
41+
this._valid = true;
42+
return;
43+
}
44+
45+
if (typeof value === 'number') {
46+
if (!Number.isSafeInteger(value)) {
47+
throw new TypeError(`Value '${value}' cannot be safely converted to Int64`);
48+
}
49+
this._value = BigInt(value);
50+
this._valid = true;
51+
return;
52+
}
53+
54+
throw new Error(`Unable to set '${value}' as Int64`);
55+
}
56+
57+
public toString() {
58+
if (this._valid) {
59+
return String(this._value);
60+
}
61+
62+
return NULL_VALUE;
63+
}
64+
}

src/scalar/timestamp.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { DataType, Timestamp as ArrowTimestamp, TimeUnit } from '@apache-arrow/esnext-esm';
2+
import { DateTime } from 'luxon';
3+
4+
import { Scalar } from './scalar.js';
5+
import { isInvalid, NULL_VALUE } from './util.js';
6+
7+
export class Timestamp implements Scalar<DateTime> {
8+
private _valid = false;
9+
private _value: DateTime = DateTime.fromMillis(0);
10+
private _unit: TimeUnit = TimeUnit.NANOSECOND;
11+
12+
public constructor(v: unknown, unit?: TimeUnit) {
13+
this.value = v;
14+
if (unit) {
15+
this._unit = unit;
16+
}
17+
return this;
18+
}
19+
20+
public get dataType(): DataType {
21+
return new ArrowTimestamp(this._unit);
22+
}
23+
24+
public get valid(): boolean {
25+
return this._valid;
26+
}
27+
28+
public get value(): DateTime {
29+
return this._value;
30+
}
31+
32+
public set value(value: unknown) {
33+
if (isInvalid(value)) {
34+
this._valid = false;
35+
return;
36+
}
37+
38+
if (value instanceof Timestamp) {
39+
this._valid = value.valid;
40+
this._value = value.value;
41+
return;
42+
}
43+
44+
let dateValue: DateTime | null = null;
45+
46+
if (typeof value === 'string') {
47+
dateValue = DateTime.fromFormat(value, 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS ZZZZ', { setZone: true });
48+
49+
if (!dateValue.isValid) {
50+
dateValue = DateTime.fromFormat(value, 'yyyy-MM-dd HH:mm:ss.SSSSSSSSS', { zone: 'utc' });
51+
}
52+
53+
if (!dateValue.isValid) {
54+
dateValue = DateTime.fromFormat(value, "yyyy-MM-dd HH:mm:ss.SSSSSSSSS'Z'", { zone: 'utc' });
55+
}
56+
57+
if (!dateValue.isValid) {
58+
dateValue = DateTime.fromISO(value, { setZone: true });
59+
}
60+
}
61+
62+
if (dateValue && dateValue.isValid) {
63+
this._value = dateValue;
64+
this._valid = true;
65+
return;
66+
}
67+
68+
throw new Error(`Unable to set '${value}' as Timestamp`);
69+
}
70+
71+
public toString(): string {
72+
if (this._valid) {
73+
return this._value.toISO()!;
74+
}
75+
76+
return NULL_VALUE;
77+
}
78+
}

0 commit comments

Comments
 (0)