HTHou commented on code in PR #15:
URL:
https://github.com/apache/iotdb-client-nodejs/pull/15#discussion_r3567833193
##########
src/utils/DataTypes.ts:
##########
@@ -99,6 +99,51 @@ export enum TSDataType {
// OBJECT = 12, // Reserved - not yet implemented
}
+/**
+ * Convert a JavaScript Date (or an already-encoded yyyyMMdd number) to the
+ * IoTDB DATE wire format: an INT32 encoded as year*10000 + month*100 + day
+ * (e.g. 2024-01-01 -> 20240101).
+ *
+ * This matches the Java client's DateUtils.parseDateExpressionToInt and the
+ * C# client. The calendar date is taken from the Date's UTC components,
+ * consistent with `new Date("2024-01-01")` which parses as UTC midnight.
+ *
+ * @param value - Date object or a yyyyMMdd integer (passed through unchanged)
+ * @returns The yyyyMMdd integer encoding
+ */
+export function parseDateToInt(value: Date | number): number {
+ if (value instanceof Date) {
+ return (
+ value.getUTCFullYear() * 10000 +
+ (value.getUTCMonth() + 1) * 100 +
+ value.getUTCDate()
+ );
+ }
+ return value;
+}
+
+/**
+ * Convert an IoTDB DATE wire value (INT32, year*10000 + month*100 + day)
+ * back to a JavaScript Date at UTC midnight of that calendar date.
+ *
+ * Inverse of {@link parseDateToInt}; matches the Java client's
+ * DateUtils.parseIntToDate.
+ *
+ * @param value - The yyyyMMdd integer (e.g. 20240101)
+ * @returns Date at UTC midnight of the encoded calendar date
+ */
+export function parseIntToDate(value: number): Date {
+ const year = Math.trunc(value / 10000);
+ const month = Math.trunc(value / 100) % 100;
+ const day = value % 100;
+ const date = new Date(Date.UTC(year, month - 1, day));
+ // Date.UTC maps years 0-99 to 1900-1999; correct that explicitly
+ if (year >= 0 && year < 100) {
+ date.setUTCFullYear(year);
+ }
+ return date;
+}
Review Comment:
Could these public helpers validate the DATE value instead of relying on
JavaScript normalization/coercion? The Java counterpart rejects years outside
1000–9999 and `LocalDate` guarantees a valid calendar date. Here, `new
Date(NaN)` produces `NaN` and the serializer silently writes `0`; numeric
`20240230` is passed through as an impossible DATE; and
`parseIntToDate(20230229)` normalizes to 2023-03-01. Since these helpers are
exported and used by both serializers, rejecting non-finite, non-integer,
out-of-range, and impossible dates would prevent silent invalid wire values.
Please add boundary tests as well.
##########
src/utils/DataTypes.ts:
##########
@@ -99,6 +99,51 @@ export enum TSDataType {
// OBJECT = 12, // Reserved - not yet implemented
}
+/**
+ * Convert a JavaScript Date (or an already-encoded yyyyMMdd number) to the
+ * IoTDB DATE wire format: an INT32 encoded as year*10000 + month*100 + day
+ * (e.g. 2024-01-01 -> 20240101).
+ *
+ * This matches the Java client's DateUtils.parseDateExpressionToInt and the
+ * C# client. The calendar date is taken from the Date's UTC components,
+ * consistent with `new Date("2024-01-01")` which parses as UTC midnight.
+ *
+ * @param value - Date object or a yyyyMMdd integer (passed through unchanged)
+ * @returns The yyyyMMdd integer encoding
+ */
+export function parseDateToInt(value: Date | number): number {
+ if (value instanceof Date) {
+ return (
+ value.getUTCFullYear() * 10000 +
+ (value.getUTCMonth() + 1) * 100 +
+ value.getUTCDate()
+ );
+ }
+ return value;
Review Comment:
The numeric DATE contract changes to `yyyyMMdd` here, but the public
documentation still defines numeric DATE values as days since the Unix epoch
(`docs/data-types.md` and both the English and Chinese tree user guides).
Because numbers are passed through unchanged, a caller following those docs and
passing `19723` for 2024-01-01 will now write the invalid wire value `19723`
instead of `20240101`. Please update all DATE documentation and examples in
this PR.
##########
src/client/Session.ts:
##########
@@ -1021,6 +1015,23 @@ export class Session {
);
}
+ // DATE columns arrive in TsBlock with wire type INT32 (1); the real DATE
+ // type is only present in the query metadata. Convert those columns'
+ // yyyyMMdd integers (e.g. 20240101) to Date objects here.
+ for (let i = 0; i < valueColumns.length; i++) {
+ if (
+ valueColumnTypes[i] === 1 &&
+ this.getDataTypeCode(dataTypes[i]) === 9
Review Comment:
Please use `columnIndex2TsBlockColumnIndexList` before deciding which
physical TsBlock columns are DATE. `dataTypes` is ordered by logical response
columns, while TsBlock columns may be deduplicated or reordered. For example,
with logical types `[DATE, INT32]`, physical values `[7, 20260713]`, and
mapping `[1, 0]`, this converts `7` to a `Date` and leaves the actual DATE as a
number. The mapping needs to be passed into `parseQueryResult` for both the
initial and fetched batches, then inverted into physical-column types. A real
TsBlock test using wire type `1` and a non-identity mapping would cover this
path.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]