Skip to content

Commit

Permalink
SNOW-1230848: Fix error related to milliseconds precision (#825)
Browse files Browse the repository at this point in the history
* Fix error related to milliseconds precision
* Add test to verify milliseconds and nanoseconds precision
  • Loading branch information
Luis Alonso Montero Marín authored Apr 18, 2024
1 parent bffaf4c commit a2d4814
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 55 deletions.
6 changes: 3 additions & 3 deletions lib/connection/result/sf_timestamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ function SfTimestamp(epochSeconds, nanoSeconds, scale, timezone, format) {
this.timezone = timezone;
this.format = format;

// create a moment object that includes the epoch seconds and the incremental nano seconds
let moment = Moment(epochSeconds * 1000);
moment.nanoSeconds = nanoSeconds;
// Milliseconds are truncated to avoid rounding issues, and the decimal part is not useful since Moment only supports milliseconds precision
const milliseconds = Math.trunc(nanoSeconds / 1000000);
let moment = Moment((epochSeconds * 1000) + milliseconds);

// set the moment's timezone
if (Util.isString(timezone)) {
Expand Down
169 changes: 117 additions & 52 deletions test/unit/connection/result/result_test_timestamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,67 @@ const Util = require('./../../../../lib/util');
const assert = require('assert');
const ResultTestCommon = require('./result_test_common');

function checkSingleTimestamp(dateRowset, timestampOutputFormat, scale, expectedJson, done, additionalValidations = undefined) {
const response =
{
'data': {
'parameters': [
{ 'name': 'TIMEZONE', 'value': 'America/Los_Angeles' },
{ 'name': 'TIMESTAMP_OUTPUT_FORMAT', 'value': timestampOutputFormat },
{ 'name': 'TIMESTAMP_NTZ_OUTPUT_FORMAT', 'value': '' },
{ 'name': 'TIMESTAMP_LTZ_OUTPUT_FORMAT', 'value': '' },
{ 'name': 'TIMESTAMP_TZ_OUTPUT_FORMAT', 'value': '' },
{ 'name': 'DATE_OUTPUT_FORMAT', 'value': 'YYYY-MM-DD' },
{ 'name': 'CLIENT_RESULT_PREFETCH_SLOTS', 'value': 2 },
{ 'name': 'CLIENT_RESULT_PREFETCH_THREADS', 'value': 1 },
{ 'name': 'CLIENT_HONOR_CLIENT_TZ_FOR_TIMESTAMP_NTZ', 'value': true },
{ 'name': 'CLIENT_USE_V1_QUERY_API', 'value': true }
],
'rowtype': [{
'name': 'C1',
'byteLength': null,
'nullable': false,
'precision': 0,
'scale': scale,
'length': null,
'type': 'timestamp_ntz'
}],
'rowset': [[dateRowset]],
'total': 1,
'returned': 1,
'queryId': 'b603b7fb-48df-48b6-bc90-25a7cb355e1d',
'databaseProvider': null,
'finalDatabaseName': null,
'finalSchemaName': null,
'finalWarehouseName': 'NEW_WH',
'finalRoleName': 'ACCOUNTADMIN',
'numberOfBinds': 0,
'statementTypeId': 4096,
'version': 0
},
'message': null,
'code': null,
'success': true
};

ResultTestCommon.testResult(
ResultTestCommon.createResultOptions(response),
function (row) {
const actualTimestamp = row.getColumnValue('C1');
assert.ok(Util.isDate(row.getColumnValue('C1')));
assert.strictEqual(actualTimestamp.toJSON(), expectedJson);
if (additionalValidations !== undefined) {
additionalValidations(actualTimestamp);
}
},
function () {
done();
}
);
}

describe('Result: test timestamp', function () {

it('select to_timestamp_ltz(\'Thu, 21 Jan 2016 06:32:44 -0800\') as C1, ' +
'to_timestamp_tz(\'Thu, 21 Jan 2016 06:32:44 -0800\') as C2, ' +
'to_timestamp_ntz(\'Thu, 21 Jan 2016 06:32:44 -0800\') as C3;',
Expand Down Expand Up @@ -84,61 +144,66 @@ describe('Result: test timestamp', function () {

it('select dateadd(ns,-1, to_timestamp_ntz(\'10000-01-01T00:00:00\', \'YYYY-MM-DD"T"HH24:MI:SS\')) AS C1;',
function (done) {
const response =
{
'data': {
'parameters': [
{ 'name': 'TIMEZONE', 'value': 'America/Los_Angeles' },
{ 'name': 'TIMESTAMP_OUTPUT_FORMAT', 'value': 'YYYY-MM-DD HH24:MI:SS.FF3' },
{ 'name': 'TIMESTAMP_NTZ_OUTPUT_FORMAT', 'value': '' },
{ 'name': 'TIMESTAMP_LTZ_OUTPUT_FORMAT', 'value': '' },
{ 'name': 'TIMESTAMP_TZ_OUTPUT_FORMAT', 'value': '' },
{ 'name': 'DATE_OUTPUT_FORMAT', 'value': 'YYYY-MM-DD' },
{ 'name': 'CLIENT_RESULT_PREFETCH_SLOTS', 'value': 2 },
{ 'name': 'CLIENT_RESULT_PREFETCH_THREADS', 'value': 1 },
{ 'name': 'CLIENT_HONOR_CLIENT_TZ_FOR_TIMESTAMP_NTZ', 'value': true },
{ 'name': 'CLIENT_USE_V1_QUERY_API', 'value': true }
],
'rowtype': [{
'name': 'C1',
'byteLength': null,
'nullable': false,
'precision': 0,
'scale': 9,
'length': null,
'type': 'timestamp_ntz'
}],
'rowset': [['253402300799.999999999']],
'total': 1,
'returned': 1,
'queryId': 'b603b7fb-48df-48b6-bc90-25a7cb355e1d',
'databaseProvider': null,
'finalDatabaseName': null,
'finalSchemaName': null,
'finalWarehouseName': 'NEW_WH',
'finalRoleName': 'ACCOUNTADMIN',
'numberOfBinds': 0,
'statementTypeId': 4096,
'version': 0
},
'message': null,
'code': null,
'success': true
};

ResultTestCommon.testResult(
ResultTestCommon.createResultOptions(response),
function (row) {
const actualTimestamp = row.getColumnValue('C1');
assert.ok(Util.isDate(row.getColumnValue('C1')));
assert.strictEqual(actualTimestamp.toJSON(), '9999-12-31 23:59:59.999');
checkSingleTimestamp(
'253402300799.999999999',
'YYYY-MM-DD HH24:MI:SS.FF3',
9,
'9999-12-31 23:59:59.999',
done,
(actualTimestamp) => {
assert.strictEqual(actualTimestamp.getNanoSeconds(), 999999999);
assert.strictEqual(actualTimestamp.getEpochSeconds(), 253402300799);
assert.strictEqual(actualTimestamp.getScale(), 9);
},
function () {
done();
}
);
});
}
);

it('select to_timestamp_ntz(\'2024-04-16T14:57:58:999\', \'YYYY-MM-DD"T"HH24:MI:SS:FF3\') AS C1;',
function (done) {
checkSingleTimestamp(
'1713279478.999',
'YYYY-MM-DD HH24:MI:SS.FF3',
3,
'2024-04-16 14:57:58.999',
done
);
}
);

it('select to_timestamp_ntz(\'2024-04-16T14:57:58:001\', \'YYYY-MM-DD"T"HH24:MI:SS:FF3\') AS C1;',
function (done) {
checkSingleTimestamp(
'1713279478.001',
'YYYY-MM-DD HH24:MI:SS.FF3',
3,
'2024-04-16 14:57:58.001',
done
);
}
);

it('select to_timestamp_ntz(\'2024-04-16T14:57:58:999999999\', \'YYYY-MM-DD"T"HH24:MI:SS:FF9\') AS C1;',
function (done) {
checkSingleTimestamp(
'1713279478.999999999',
'YYYY-MM-DD HH24:MI:SS.FF9',
9,
'2024-04-16 14:57:58.999999999',
done
);
}
);

it('select to_timestamp_ntz(\'2024-04-16T14:57:58:000000001\', \'YYYY-MM-DD"T"HH24:MI:SS:FF9\')) AS C1;',
function (done) {
checkSingleTimestamp(
'1713279478.000000001',
'YYYY-MM-DD HH24:MI:SS.FF9',
9,
'2024-04-16 14:57:58.000000001',
done
);
}
);
});

0 comments on commit a2d4814

Please sign in to comment.