From 4c6e4b4433b9392e190ca782bdcc6e78b61371fd Mon Sep 17 00:00:00 2001 From: seunghun Date: Mon, 26 Jun 2017 13:01:46 +0900 Subject: [PATCH] Implement Protocol v7 and Timezone (#53) * update protocol to v7 * add timezone to CASConstants * add parsing about timezone * update testcase for PROTOCOL_V7 * improve testcase for calling createConnection as default * implement timezone for PROTOCOL_V7 * add test code for Timezone * add 'moment-timezone' because DST issue --- package.json | 3 + src/constants/CASConstants.js | 31 +- src/packets/ExecuteQueryPacket.js | 16 +- src/packets/GetSchemaPacket.js | 8 +- src/packets/PacketReader.js | 47 +++ src/packets/PrepareExecutePacket.js | 8 +- src/utils/Timezone.js | 182 +++++++++ test/CUBRID.createConnection.js | 5 + test/CUBRIDConnection.getSchema.js | 56 ++- test/Timezone.js | 602 ++++++++++++++++++++++++++++ 10 files changed, 938 insertions(+), 20 deletions(-) create mode 100644 src/utils/Timezone.js create mode 100644 test/Timezone.js diff --git a/package.json b/package.json index 7b106fa..ec8022f 100644 --- a/package.json +++ b/package.json @@ -34,5 +34,8 @@ "eslint": "3.6.1", "istanbul": "0.4.5", "mocha": "3.0.2" + }, + "dependencies": { + "moment-timezone": "^0.5.13" } } diff --git a/src/constants/CASConstants.js b/src/constants/CASConstants.js index 07af191..5f944ed 100644 --- a/src/constants/CASConstants.js +++ b/src/constants/CASConstants.js @@ -188,7 +188,11 @@ exports.CUBRIDDataType = { CCI_U_TYPE_DATETIME : 22, CCI_U_TYPE_BLOB : 23, CCI_U_TYPE_CLOB : 24, - CCI_U_TYPE_ENUM : 25 + CCI_U_TYPE_ENUM : 25, + CCI_U_TYPE_TIMESTAMPTZ : 29, + CCI_U_TYPE_TIMESTAMPLTZ : 30, + CCI_U_TYPE_DATETIMETZ : 31, + CCI_U_TYPE_DATETIMELTZ : 32 }; /** @@ -246,6 +250,14 @@ exports.getCUBRIDDataTypeName = function (type) { return 'ENUM'; case this.CUBRIDDataType.CCI_U_TYPE_RESULTSET: return 'Resultset'; + case this.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPTZ: + return 'TimestampTz'; + case this.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPLTZ: + return 'TimestampLtz'; + case this.CUBRIDDataType.CCI_U_TYPE_DATETIMETZ: + return 'DateTimeTz'; + case this.CUBRIDDataType.CCI_U_TYPE_DATETIMELTZ: + return 'DateTimeLtz'; default: return 'UNKNOWN'; } @@ -307,6 +319,14 @@ exports.getCUBRIDDataTypeNumber = function (type) { return this.CUBRIDDataType.CCI_U_TYPE_CLOB; case 'resultset': return this.CUBRIDDataType.CCI_U_TYPE_RESULTSET; + case 'timestamptz': + return this.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPTZ; + case 'timestampltz': + return this.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPLTZ; + case 'datetimetz': + return this.CUBRIDDataType.CCI_U_TYPE_DATETIMETZ; + case 'datetimeltz': + return this.CUBRIDDataType.CCI_U_TYPE_DATETIMELTZ; default: return this.CUBRIDDataType.CCI_U_TYPE_UNKNOWN; } @@ -472,9 +492,10 @@ exports.CAS_PROTOCOL_VERSION = (function getProtocolVersion() { // const CAS_PROTOCOL_VERSION_3 = /* since 8.4.3 */3; // const CAS_PROTOCOL_VERSION_4 = /* since 9.1.0 */4; // const CAS_PROTOCOL_VERSION_5 = /* since 9.2.0 */5; - const CAS_PROTOCOL_VERSION_6 = /* since 9.2.26 */6; + // const CAS_PROTOCOL_VERSION_6 = /* since 9.2.26 */6; + const CAS_PROTOCOL_VERSION_7 = /* since 10.0.0 */7; - return CAS_PROTOCOL_VERSION_6; + return CAS_PROTOCOL_VERSION_7; })(); exports.CAS_VERSION = CAS_PROTO_INDICATOR | exports.CAS_PROTOCOL_VERSION; @@ -485,8 +506,8 @@ exports.CAS_CLIENT_JDBC = 3; exports.CAS_MAGIC_STRING = 'CUBRK'; exports.getProtocolVersion = function (version) { - // At this moment `node-cubrid` supports at most protocol version 6. - for (let protocolVersion = 0; protocolVersion < 7; ++protocolVersion) { + // At this moment `node-cubrid` supports at most protocol version 7. + for (let protocolVersion = 0; protocolVersion < 8; ++protocolVersion) { if ((CAS_PROTO_INDICATOR | protocolVersion) === version) { return protocolVersion; } diff --git a/src/packets/ExecuteQueryPacket.js b/src/packets/ExecuteQueryPacket.js index 6259b3f..c875fef 100644 --- a/src/packets/ExecuteQueryPacket.js +++ b/src/packets/ExecuteQueryPacket.js @@ -110,10 +110,16 @@ ExecuteQueryPacket.prototype.parse = function (parser) { let i; let info; let len; + const MASK_TYPE_HAS_2_BYTES = 0x80; for (i = 0; i < this.columnCount; i++) { info = new ColumnMetaData(); - info.ColumnType = parser._parseByte(); // Column type + let legacyType = parser._parseByte(); // Column type before PROTOCOL_V7 + if ((legacyType & MASK_TYPE_HAS_2_BYTES) === 128) { + info.ColumnType = parser._parseByte(); // Column type + } else { + info.ColumnType = legacyType; + } info.scale = parser._parseShort(); // Scale info.precision = parser._parseInt(); // Precision len = parser._parseInt(); @@ -312,6 +318,14 @@ function _readValue(parser, type, size) { case CAS.CUBRIDDataType.CCI_U_TYPE_TIMESTAMP: return parser._parseTimeStamp(); + case CAS.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPTZ: + case CAS.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPLTZ: + return parser._parseTimeStampTz(size); + + case CAS.CUBRIDDataType.CCI_U_TYPE_DATETIMETZ: + case CAS.CUBRIDDataType.CCI_U_TYPE_DATETIMELTZ: + return parser._parseDateTimeTz(size); + case CAS.CUBRIDDataType.CCI_U_TYPE_OBJECT: return parser._parseObject(); diff --git a/src/packets/GetSchemaPacket.js b/src/packets/GetSchemaPacket.js index b32d387..d2c7487 100644 --- a/src/packets/GetSchemaPacket.js +++ b/src/packets/GetSchemaPacket.js @@ -90,11 +90,17 @@ GetSchemaPacket.prototype.parseRequestSchema = function (parser) { const numColInfo = parser._parseInt(); // Number of columns this.infoArray = []; + const MASK_TYPE_HAS_2_BYTES = 0x80; for (let i = 0; i < numColInfo; ++i) { let info = new ColumnMetaData(); - info.ColumnType = parser._parseByte(); // Column data type + let legacyType = parser._parseByte(); // Column data type + if ((legacyType & MASK_TYPE_HAS_2_BYTES) === 128) { + info.ColumnType = parser._parseByte(); // Column data type + } else { + info.ColumnType = legacyType; + } info.scale = parser._parseShort(); // Scale info.precision = parser._parseInt(); // Precision diff --git a/src/packets/PacketReader.js b/src/packets/PacketReader.js index 9a63ac3..c3c0fc7 100644 --- a/src/packets/PacketReader.js +++ b/src/packets/PacketReader.js @@ -3,6 +3,7 @@ const CAS = require('../constants/CASConstants'); const DATA_TYPES = require('../constants/DataTypes'); const ErrorMessages = require('../constants/ErrorMessages'); +const Timezone = require('../utils/Timezone'); module.exports = PacketReader; @@ -236,6 +237,52 @@ PacketReader.prototype._parseTimeStamp = function () { return date; }; +/** + * Returns a timestamptz value from the internal buffer + * @param size + * @returns {Timezone} + */ +PacketReader.prototype._parseTimeStampTz = function(size) { + const tmp_position = this._offset; + const timestamp = this._parseTimeStamp.call(this); + const timestamp_size = this._offset - tmp_position; + let timezone; + + if (timestamp_size > 0) { + const timezoneLength = size - timestamp_size - 1; + timezone = this._buffer.slice(this._offset, this._offset + timezoneLength); + this._offset += size - timestamp_size; + } else { + timezone = ''; + this._offset++; + } + + return new Timezone(timestamp, timezone); +}; + +/** + * Returns a datetimetz value from the internal buffer + * @param size + * @returns {Timezone} + */ +PacketReader.prototype._parseDateTimeTz = function(size) { + const tmp_position = this._offset; + const datetime = this._parseDateTime.call(this); + const datetime_size = this._offset - tmp_position; + let timezone; + + if (datetime_size > 0) { + const timezoneLength = size - datetime_size - 1; + timezone = this._buffer.slice(this._offset, this._offset + timezoneLength); + this._offset += size - datetime_size; + } else { + timezone = ''; + this._offset++; + } + + return new Timezone(datetime, timezone); +}; + /** * Returns a char value from the internal buffer * @return {String} diff --git a/src/packets/PrepareExecutePacket.js b/src/packets/PrepareExecutePacket.js index 0b4166c..76ac050 100644 --- a/src/packets/PrepareExecutePacket.js +++ b/src/packets/PrepareExecutePacket.js @@ -93,11 +93,17 @@ PrepareExecutePacket.prototype.parsePrepare = function (parser) { this.isUpdatable = parser._parseByte() === 1; // Updatable? this.columnCount = parser._parseInt(); // Column count this.infoArray = []; + const MASK_TYPE_HAS_2_BYTES = 0x80; for (let i = 0; i < this.columnCount; ++i) { let info = new ColumnMetaData(); - info.ColumnType = parser._parseByte(); // Column type + let legacyType = parser._parseByte(); // Column type + if ((legacyType & MASK_TYPE_HAS_2_BYTES) === 128) { + info.ColumnType = parser._parseByte(); + } else { + info.ColumnType = legacyType; + } info.scale = parser._parseShort(); // Scale info.precision = parser._parseInt(); // Precision diff --git a/src/utils/Timezone.js b/src/utils/Timezone.js new file mode 100644 index 0000000..b8b766d --- /dev/null +++ b/src/utils/Timezone.js @@ -0,0 +1,182 @@ +'use strict'; +const moment = require('moment-timezone'); + +module.exports = Timezone; + +/** + * Constructor + * @param datetime + * @param timezone + */ +function Timezone(datetime, timezone) { + this.datetime = datetime; + + if (timezone) { + this.timezone = timezone.toString(); + const tz = this.timezone.split(' '); + this.region = tz[0]; + + if (!tz[1]) { + // create from moment + this.tzd = moment.tz(this.datetime, this.region).format('z') + } else { + this.tzd = tz[1]; + } + + const timeOffset = moment.tz(this.datetime, this.region).format('Z').split(':'); + this.tzh = timeOffset[0]; + this.tzm = timeOffset[1]; + } else { + this.timezone = ''; + this.tzd = ''; + this.tzh = ''; + this.tzm = ''; + } +} + +/** + * Returns 'YYYY-MM-DD HH24:MI:SS TIMEZONE' format + * @returns {string} + */ +Timezone.prototype.toString = function() { + return `${this.format('YYYY-MM-DD HH24:MI:SS.FF')}${(this.timezone ? ` ${this.timezone}` : ``)}`; +}; + +/** + * This format based Date/Time format from http://www.cubrid.org/manual/10_0/en/sql/function/typecast_fn.html#to-char-date-time + * @param format + * @returns {String} + */ +Timezone.prototype.format = function(format) { + if (!this.datetime) return ''; + + const weeks = [ + 'Sunday', + 'Monday', + 'Tuesday', + 'Wednesday', + 'Thursday', + 'Friday', + 'Saturday']; + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December']; + const date = this.datetime; + const that = this; + + let am = (/AM|A\.M\./i).exec(format); + let pm = (/PM|P\.M\./i).exec(format); + if (am) { + am = am[0]; + const code = am.charCodeAt(0) + 15; + pm = am.replace(/A/i, String.fromCharCode(code)); + } else if (pm) { + pm = pm[0]; + const code = pm.charCodeAt(0) - 15; + am = pm.replace(/P/i, String.fromCharCode(code)); + } + + format = format.toUpperCase(); + const formatRex = /(CC|YYYY|YY|Q|MM|MONTH|MON|DD|DAY|DY|D|d|AM|PM|A\.M\.|P\.M\.|HH12|HH24|HH|MI|SS|FF|TZD|TZH|TZM)/g; + + return format.replace(formatRex, function($1) { + switch($1) { + case 'CC': + return Math.floor(parseInt(date.getUTCFullYear() / 100)) + 1; + case 'YYYY': + return date.getUTCFullYear(); + case 'YY': + return _zeroPadding(date.getUTCFullYear() % 100); + case 'Q': { + const mon = date.getMonth(); + if (mon < 3) return 1; + else if (mon < 6) return 2; + else if (mon < 9) return 3; + else return 4; + } case 'MM': + return _zeroPadding(date.getMonth() + 1); + case 'MONTH': + return months[date.getMonth()]; + case 'MON': + return months[date.getMonth()].substr(0, 3); + case 'DD': + return _zeroPadding(date.getUTCDate()); + case 'DAY': + return weeks[date.getUTCDay()]; + case 'DY': + return weeks[date.getUTCDay()].substr(0, 3); + case 'D': + case 'd': + return (date.getUTCDay() == 0) ? 7 : date.getUTCDay(); + case 'AM': + case 'A.M.': + case 'PM': + case 'P.M.': + return (date.getUTCHours() < 12) ? am : pm; + case 'HH': + case 'HH12': { + const hour = date.getUTCHours() % 12; + return _zeroPadding((hour) ? hour : date.getUTCHours()); + } case 'HH24': + return _zeroPadding(date.getUTCHours()); + case 'MI': + return _zeroPadding(date.getUTCMinutes()); + case 'SS': + return _zeroPadding(date.getUTCSeconds()); + case 'FF': + return _zeroPadding(date.getMilliseconds(), true); + case 'TZD': + return that.tzd; + case 'TZH': + return that.tzh; + case 'TZM': + return that.tzm; + default: + return $1; + } + }); +}; + +/** + * Return the number of milliseconds between 1 January 1970 00:00:00 UTC and Timezone.datetime + * @returns {Number} + */ +Timezone.prototype.valueOf = function() { + return Date.prototype.valueOf.call(this.datetime); +}; + +/** + * Return the number of offset for this timezone + * @returns {Number} + */ +Timezone.prototype.getOffset = function() { + const zone = moment.tz.zone(this.region); + return zone.parse(this.datetime) * 60 * 1000; +}; + +function _zeroPadding(value, isMs) { + let data; + if (value < 10) { + data = `0${value}`; + } else { + data = value; + } + + if (isMs) { + if (value < 100) { + data = `0${data}` + } + } + + return data; +} \ No newline at end of file diff --git a/test/CUBRID.createConnection.js b/test/CUBRID.createConnection.js index 8c306c7..555b490 100644 --- a/test/CUBRID.createConnection.js +++ b/test/CUBRID.createConnection.js @@ -78,6 +78,11 @@ describe('CUBRID', function () { .then(() => { return client.close(); }) + .catch(err => { + if ((config.host === err.address) && (config.port === err.port) && (err.code === 'ECONNREFUSED')) { + throw err; + } + }) .then(() => { ++closedCount; }); diff --git a/test/CUBRIDConnection.getSchema.js b/test/CUBRIDConnection.getSchema.js index 90b4abe..c8c19c9 100644 --- a/test/CUBRIDConnection.getSchema.js +++ b/test/CUBRIDConnection.getSchema.js @@ -12,7 +12,11 @@ describe('CUBRIDConnection', function () { return client .getSchema(CAS.CUBRIDSchemaType.CCI_SCH_CLASS) .then(schema => { - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(34); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(32); @@ -34,7 +38,11 @@ describe('CUBRIDConnection', function () { return done(err); } - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(34); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(32); @@ -54,7 +62,11 @@ describe('CUBRIDConnection', function () { return client .getSchema(CAS.CUBRIDSchemaType.CCI_SCH_VCLASS) .then(schema => { - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(18); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(16); @@ -76,7 +88,11 @@ describe('CUBRIDConnection', function () { return done(err); } - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(18); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(16); @@ -96,7 +112,11 @@ describe('CUBRIDConnection', function () { return client .getSchema(CAS.CUBRIDSchemaType.CCI_SCH_CLASS_PRIVILEGE) .then(schema => { - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(98); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(96); @@ -135,7 +155,11 @@ describe('CUBRIDConnection', function () { return done(err); } - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(98); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(96); @@ -175,7 +199,7 @@ describe('CUBRIDConnection', function () { expect(schema) .to.be.an('array') .with.length(0); - + return client.close(); }); }); @@ -339,7 +363,7 @@ describe('CUBRIDConnection', function () { let table1 = schema[0]; let table2 = schema[1]; - if ([/* 9.0.0 */2, /* 9.1.0 */4].indexOf(client.brokerInfo.protocolVersion) > -1) { + if ([/* 9.0.0 */2, /* 9.1.0 */4, /* since 9.2.0 */5, /* since 9.2.26 */6, /* since 10.0.0 */7].indexOf(client.brokerInfo.protocolVersion) > -1) { let t = table1; table1 = table2; table2 = t; @@ -460,7 +484,7 @@ describe('CUBRIDConnection', function () { let table1 = schema[0]; let table2 = schema[1]; - if ([/* 9.0.0 */2, /* 9.1.0 */4].indexOf(client.brokerInfo.protocolVersion) > -1) { + if ([/* 9.0.0 */2, /* 9.1.0 */4, /* since 9.2.0 */5, /* since 9.2.26 */6, /* since 10.0.0 */7].indexOf(client.brokerInfo.protocolVersion) > -1) { let t = table1; table1 = table2; table2 = t; @@ -642,7 +666,11 @@ describe('CUBRIDConnection', function () { return client .getSchema(CAS.CUBRIDSchemaType.CCI_SCH_ATTRIBUTE) .then(schema => { - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(229); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(191); @@ -653,7 +681,7 @@ describe('CUBRIDConnection', function () { } const table = schema[0]; - + expect(table) .to.be.an('object') .to.have.property('Name') @@ -721,7 +749,11 @@ describe('CUBRIDConnection', function () { return done(err); } - if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { + if (client.brokerInfo.protocolVersion === /* 10.0.0 */7) { + expect(schema) + .to.be.an('array') + .with.length(229); + } else if ([/* 8.4.1 */1, /* 8.4.3 */3].indexOf(client.brokerInfo.protocolVersion) > -1) { expect(schema) .to.be.an('array') .with.length(191); diff --git a/test/Timezone.js b/test/Timezone.js new file mode 100644 index 0000000..583b6b6 --- /dev/null +++ b/test/Timezone.js @@ -0,0 +1,602 @@ +'use strict'; + +const expect = require('chai').expect; +const Timezone = require('../src/utils/Timezone'); +const testSetup = require('./testSetup'); +// const CAS = require('../src/constants/CASConstants'); + +// test the Timezone module's function or method +describe('Timezone', function() { + describe('format', function() { + it('should success to validate the return values', function() { + let timezone = 'Asia/Seoul KST'; + let timezoneObject; + + // 1. format: 'CC' and 'cc' + timezoneObject = new Timezone(new Date(Date.UTC(1970, 0, 1)), timezone); + expect(timezoneObject.format('CC')).to.equal('20'); + expect(timezoneObject.format('cc')).to.equal('20'); + + timezoneObject = new Timezone(new Date(Date.UTC(2000, 0, 1)), timezone); + expect(timezoneObject.format('CC')).to.equal('21'); + expect(timezoneObject.format('cc')).to.equal('21'); + + timezoneObject = new Timezone(new Date(Date.UTC(2100, 0, 1)), timezone); + expect(timezoneObject.format('CC')).to.equal('22'); + expect(timezoneObject.format('cc')).to.equal('22'); + + timezoneObject = new Timezone(new Date(Date.UTC(2200, 0, 1)), timezone); + expect(timezoneObject.format('CC')).to.equal('23'); + expect(timezoneObject.format('cc')).to.equal('23'); + + + // 2. format 'YYYY' and 'yyyy' + timezoneObject = new Timezone(new Date(Date.UTC(1970, 0, 1)), timezone); + expect(timezoneObject.format('YYYY')).to.equal('1970'); + expect(timezoneObject.format('yyyy')).to.equal('1970'); + + timezoneObject = new Timezone(new Date(Date.UTC(2000, 0, 1)), timezone); + expect(timezoneObject.format('YYYY')).to.equal('2000'); + expect(timezoneObject.format('yyyy')).to.equal('2000'); + + timezoneObject = new Timezone(new Date(Date.UTC(2100, 0, 1)), timezone); + expect(timezoneObject.format('YYYY')).to.equal('2100'); + expect(timezoneObject.format('yyyy')).to.equal('2100'); + + timezoneObject = new Timezone(new Date(Date.UTC(2200, 0, 1)), timezone); + expect(timezoneObject.format('YYYY')).to.equal('2200'); + expect(timezoneObject.format('yyyy')).to.equal('2200'); + + timezoneObject = new Timezone(new Date(), timezone); + expect(parseInt(timezoneObject.format('YYYY'))).to.equal(timezoneObject.datetime.getUTCFullYear()); + expect(parseInt(timezoneObject.format('yyyy'))).to.equal(timezoneObject.datetime.getUTCFullYear()); + + + // 3. format 'YY' and 'yy' + timezoneObject = new Timezone(new Date(Date.UTC(1970, 0, 1)), timezone); + expect(timezoneObject.format('YY')).to.equal('70'); + expect(timezoneObject.format('yy')).to.equal('70'); + + timezoneObject = new Timezone(new Date(Date.UTC(2000, 0, 1)), timezone); + expect(timezoneObject.format('YY')).to.equal('00'); + expect(timezoneObject.format('yy')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2010, 0, 1)), timezone); + expect(timezoneObject.format('YY')).to.equal('10'); + expect(timezoneObject.format('yy')).to.equal('10'); + + timezoneObject = new Timezone(new Date(Date.UTC(2020, 0, 1)), timezone); + expect(timezoneObject.format('YY')).to.equal('20'); + expect(timezoneObject.format('yy')).to.equal('20'); + + timezoneObject = new Timezone(new Date(), timezone); + expect(parseInt(timezoneObject.format('YY'))).to.equal(timezoneObject.datetime.getUTCFullYear() % 100); + expect(parseInt(timezoneObject.format('yy'))).to.equal(timezoneObject.datetime.getUTCFullYear() % 100); + + + // 4. format 'Q' and 'q', 'MM' and 'mm', 'MONTH' and 'month', 'MON' and 'mon' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('1'); + expect(timezoneObject.format('q')).to.equal('1'); + expect(timezoneObject.format('MM')).to.equal('01'); + expect(timezoneObject.format('mm')).to.equal('01'); + expect(timezoneObject.format('MONTH')).to.equal('January'); + expect(timezoneObject.format('month')).to.equal('January'); + expect(timezoneObject.format('MON')).to.equal('Jan'); + expect(timezoneObject.format('mon')).to.equal('Jan'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 1, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('1'); + expect(timezoneObject.format('q')).to.equal('1'); + expect(timezoneObject.format('MM')).to.equal('02'); + expect(timezoneObject.format('mm')).to.equal('02'); + expect(timezoneObject.format('MONTH')).to.equal('February'); + expect(timezoneObject.format('month')).to.equal('February'); + expect(timezoneObject.format('MON')).to.equal('Feb'); + expect(timezoneObject.format('mon')).to.equal('Feb'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 2, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('1'); + expect(timezoneObject.format('q')).to.equal('1'); + expect(timezoneObject.format('MM')).to.equal('03'); + expect(timezoneObject.format('mm')).to.equal('03'); + expect(timezoneObject.format('MONTH')).to.equal('March'); + expect(timezoneObject.format('month')).to.equal('March'); + expect(timezoneObject.format('MON')).to.equal('Mar'); + expect(timezoneObject.format('mon')).to.equal('Mar'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 3, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('2'); + expect(timezoneObject.format('q')).to.equal('2'); + expect(timezoneObject.format('MM')).to.equal('04'); + expect(timezoneObject.format('mm')).to.equal('04'); + expect(timezoneObject.format('MONTH')).to.equal('April'); + expect(timezoneObject.format('month')).to.equal('April'); + expect(timezoneObject.format('MON')).to.equal('Apr'); + expect(timezoneObject.format('mon')).to.equal('Apr'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 4, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('2'); + expect(timezoneObject.format('q')).to.equal('2'); + expect(timezoneObject.format('MM')).to.equal('05'); + expect(timezoneObject.format('mm')).to.equal('05'); + expect(timezoneObject.format('MONTH')).to.equal('May'); + expect(timezoneObject.format('month')).to.equal('May'); + expect(timezoneObject.format('MON')).to.equal('May'); + expect(timezoneObject.format('mon')).to.equal('May'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 5, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('2'); + expect(timezoneObject.format('q')).to.equal('2'); + expect(timezoneObject.format('MM')).to.equal('06'); + expect(timezoneObject.format('mm')).to.equal('06'); + expect(timezoneObject.format('MONTH')).to.equal('June'); + expect(timezoneObject.format('month')).to.equal('June'); + expect(timezoneObject.format('MON')).to.equal('Jun'); + expect(timezoneObject.format('mon')).to.equal('Jun'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 6, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('3'); + expect(timezoneObject.format('q')).to.equal('3'); + expect(timezoneObject.format('MM')).to.equal('07'); + expect(timezoneObject.format('mm')).to.equal('07'); + expect(timezoneObject.format('MONTH')).to.equal('July'); + expect(timezoneObject.format('month')).to.equal('July'); + expect(timezoneObject.format('MON')).to.equal('Jul'); + expect(timezoneObject.format('mon')).to.equal('Jul'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 7, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('3'); + expect(timezoneObject.format('q')).to.equal('3'); + expect(timezoneObject.format('MM')).to.equal('08'); + expect(timezoneObject.format('mm')).to.equal('08'); + expect(timezoneObject.format('MONTH')).to.equal('August'); + expect(timezoneObject.format('month')).to.equal('August'); + expect(timezoneObject.format('MON')).to.equal('Aug'); + expect(timezoneObject.format('mon')).to.equal('Aug'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 8, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('3'); + expect(timezoneObject.format('q')).to.equal('3'); + expect(timezoneObject.format('MM')).to.equal('09'); + expect(timezoneObject.format('mm')).to.equal('09'); + expect(timezoneObject.format('MONTH')).to.equal('September'); + expect(timezoneObject.format('month')).to.equal('September'); + expect(timezoneObject.format('MON')).to.equal('Sep'); + expect(timezoneObject.format('mon')).to.equal('Sep'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 9, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('4'); + expect(timezoneObject.format('q')).to.equal('4'); + expect(timezoneObject.format('MM')).to.equal('10'); + expect(timezoneObject.format('mm')).to.equal('10'); + expect(timezoneObject.format('MONTH')).to.equal('October'); + expect(timezoneObject.format('month')).to.equal('October'); + expect(timezoneObject.format('MON')).to.equal('Oct'); + expect(timezoneObject.format('mon')).to.equal('Oct'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 10, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('4'); + expect(timezoneObject.format('q')).to.equal('4'); + expect(timezoneObject.format('MM')).to.equal('11'); + expect(timezoneObject.format('mm')).to.equal('11'); + expect(timezoneObject.format('MONTH')).to.equal('November'); + expect(timezoneObject.format('month')).to.equal('November'); + expect(timezoneObject.format('MON')).to.equal('Nov'); + expect(timezoneObject.format('mon')).to.equal('Nov'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 11, 1)), timezone); + expect(timezoneObject.format('Q')).to.equal('4'); + expect(timezoneObject.format('q')).to.equal('4'); + expect(timezoneObject.format('MM')).to.equal('12'); + expect(timezoneObject.format('mm')).to.equal('12'); + expect(timezoneObject.format('MONTH')).to.equal('December'); + expect(timezoneObject.format('month')).to.equal('December'); + expect(timezoneObject.format('MON')).to.equal('Dec'); + expect(timezoneObject.format('mon')).to.equal('Dec'); + + + // 5. format 'DD' and 'dd', 'DAY' and 'day', 'DY' and 'dy', 'D' and 'd' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1)), timezone); + expect(timezoneObject.format('DD')).to.equal('01'); + expect(timezoneObject.format('dd')).to.equal('01'); + expect(timezoneObject.format('DAY')).to.equal('Sunday'); + expect(timezoneObject.format('day')).to.equal('Sunday'); + expect(timezoneObject.format('DY')).to.equal('Sun'); + expect(timezoneObject.format('dy')).to.equal('Sun'); + expect(timezoneObject.format('D')).to.equal('7'); + expect(timezoneObject.format('d')).to.equal('7'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 3, 15)), timezone); + expect(timezoneObject.format('DD')).to.equal('15'); + expect(timezoneObject.format('dd')).to.equal('15'); + expect(timezoneObject.format('DAY')).to.equal('Saturday'); + expect(timezoneObject.format('day')).to.equal('Saturday'); + expect(timezoneObject.format('DY')).to.equal('Sat'); + expect(timezoneObject.format('dy')).to.equal('Sat'); + expect(timezoneObject.format('D')).to.equal('6'); + expect(timezoneObject.format('d')).to.equal('6'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 8, 20)), timezone); + expect(timezoneObject.format('DD')).to.equal('20'); + expect(timezoneObject.format('dd')).to.equal('20'); + expect(timezoneObject.format('DAY')).to.equal('Wednesday'); + expect(timezoneObject.format('day')).to.equal('Wednesday'); + expect(timezoneObject.format('DY')).to.equal('Wed'); + expect(timezoneObject.format('dy')).to.equal('Wed'); + expect(timezoneObject.format('D')).to.equal('3'); + expect(timezoneObject.format('d')).to.equal('3'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 11, 25)), timezone); + expect(timezoneObject.format('DD')).to.equal('25'); + expect(timezoneObject.format('dd')).to.equal('25'); + expect(timezoneObject.format('DAY')).to.equal('Monday'); + expect(timezoneObject.format('day')).to.equal('Monday'); + expect(timezoneObject.format('DY')).to.equal('Mon'); + expect(timezoneObject.format('dy')).to.equal('Mon'); + expect(timezoneObject.format('D')).to.equal('1'); + expect(timezoneObject.format('d')).to.equal('1'); + + + // 6. format 'HH12' and 'hh12', 'HH' and 'hh', 'HH24' and 'hh24' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), timezone); + expect(timezoneObject.format('HH12')).to.equal('00'); + expect(timezoneObject.format('hh12')).to.equal('00'); + expect(timezoneObject.format('HH')).to.equal('00'); + expect(timezoneObject.format('hh')).to.equal('00'); + expect(timezoneObject.format('HH24')).to.equal('00'); + expect(timezoneObject.format('hh24')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 12, 0, 0)), timezone); + expect(timezoneObject.format('HH12')).to.equal('12'); + expect(timezoneObject.format('hh12')).to.equal('12'); + expect(timezoneObject.format('HH')).to.equal('12'); + expect(timezoneObject.format('hh')).to.equal('12'); + expect(timezoneObject.format('HH24')).to.equal('12'); + expect(timezoneObject.format('hh24')).to.equal('12'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 15, 0, 0)), timezone); + expect(timezoneObject.format('HH12')).to.equal('03'); + expect(timezoneObject.format('hh12')).to.equal('03'); + expect(timezoneObject.format('HH')).to.equal('03'); + expect(timezoneObject.format('hh')).to.equal('03'); + expect(timezoneObject.format('HH24')).to.equal('15'); + expect(timezoneObject.format('hh24')).to.equal('15'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 20, 0, 0)), timezone); + expect(timezoneObject.format('HH12')).to.equal('08'); + expect(timezoneObject.format('hh12')).to.equal('08'); + expect(timezoneObject.format('HH')).to.equal('08'); + expect(timezoneObject.format('hh')).to.equal('08'); + expect(timezoneObject.format('HH24')).to.equal('20'); + expect(timezoneObject.format('hh24')).to.equal('20'); + + + // 7. format 'AM' or 'PM', 'A.M.' or 'P.M.' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), timezone); + expect(timezoneObject.format('AM')).to.equal('AM'); + expect(timezoneObject.format('Am')).to.equal('Am'); + expect(timezoneObject.format('am')).to.equal('am'); + expect(timezoneObject.format('A.M.')).to.equal('A.M.'); + expect(timezoneObject.format('A.m.')).to.equal('A.m.'); + expect(timezoneObject.format('a.m.')).to.equal('a.m.'); + expect(timezoneObject.format('PM')).to.equal('AM'); + expect(timezoneObject.format('Pm')).to.equal('Am'); + expect(timezoneObject.format('pm')).to.equal('am'); + expect(timezoneObject.format('P.M.')).to.equal('A.M.'); + expect(timezoneObject.format('P.m.')).to.equal('A.m.'); + expect(timezoneObject.format('p.m.')).to.equal('a.m.'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 13, 0, 0)), timezone); + expect(timezoneObject.format('AM')).to.equal('PM'); + expect(timezoneObject.format('Am')).to.equal('Pm'); + expect(timezoneObject.format('am')).to.equal('pm'); + expect(timezoneObject.format('A.M.')).to.equal('P.M.'); + expect(timezoneObject.format('A.m.')).to.equal('P.m.'); + expect(timezoneObject.format('a.m.')).to.equal('p.m.'); + expect(timezoneObject.format('PM')).to.equal('PM'); + expect(timezoneObject.format('Pm')).to.equal('Pm'); + expect(timezoneObject.format('pm')).to.equal('pm'); + expect(timezoneObject.format('P.M.')).to.equal('P.M.'); + expect(timezoneObject.format('P.m.')).to.equal('P.m.'); + expect(timezoneObject.format('p.m.')).to.equal('p.m.'); + + + // 8. format 'MI' and 'mi' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), timezone); + expect(timezoneObject.format('MI')).to.equal('00'); + expect(timezoneObject.format('mi')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 5, 0)), timezone); + expect(timezoneObject.format('MI')).to.equal('05'); + expect(timezoneObject.format('mi')).to.equal('05'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 35, 0)), timezone); + expect(timezoneObject.format('MI')).to.equal('35'); + expect(timezoneObject.format('mi')).to.equal('35'); + + + // 9. format 'SS' and 'ss' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), timezone); + expect(timezoneObject.format('SS')).to.equal('00'); + expect(timezoneObject.format('ss')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 5)), timezone); + expect(timezoneObject.format('SS')).to.equal('05'); + expect(timezoneObject.format('ss')).to.equal('05'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 35)), timezone); + expect(timezoneObject.format('SS')).to.equal('35'); + expect(timezoneObject.format('ss')).to.equal('35'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 60)), timezone); + expect(timezoneObject.format('SS')).to.equal('00'); + expect(timezoneObject.format('ss')).to.equal('00'); + + + // 10. format 'FF' and 'ff' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), timezone); + expect(timezoneObject.format('FF')).to.equal('000'); + expect(timezoneObject.format('ff')).to.equal('000'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0, 10)), timezone); + expect(timezoneObject.format('FF')).to.equal('010'); + expect(timezoneObject.format('ff')).to.equal('010'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0, 100)), timezone); + expect(timezoneObject.format('FF')).to.equal('100'); + expect(timezoneObject.format('ff')).to.equal('100'); + + + // 11. format 'TZD' and 'tzd', 'TZH' and 'tzh', 'TZM' and 'tzm' + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), timezone); + expect(timezoneObject.format('TZD')).to.equal('KST'); + expect(timezoneObject.format('tzd')).to.equal('KST'); + expect(timezoneObject.format('TZH')).to.equal('+09'); + expect(timezoneObject.format('tzh')).to.equal('+09'); + expect(timezoneObject.format('TZM')).to.equal('00'); + expect(timezoneObject.format('tzm')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), 'UTC UTC'); + expect(timezoneObject.format('TZD')).to.equal('UTC'); + expect(timezoneObject.format('tzd')).to.equal('UTC'); + expect(timezoneObject.format('TZH')).to.equal('+00'); + expect(timezoneObject.format('tzh')).to.equal('+00'); + expect(timezoneObject.format('TZM')).to.equal('00'); + expect(timezoneObject.format('tzm')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), 'Europe/London BST'); + expect(timezoneObject.format('TZD')).to.equal('BST'); + expect(timezoneObject.format('tzd')).to.equal('BST'); + expect(timezoneObject.format('TZH')).to.equal('+00'); + expect(timezoneObject.format('tzh')).to.equal('+00'); + expect(timezoneObject.format('TZM')).to.equal('00'); + expect(timezoneObject.format('tzm')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), 'America/Los_Angeles PDT'); + expect(timezoneObject.format('TZD')).to.equal('PDT'); + expect(timezoneObject.format('tzd')).to.equal('PDT'); + expect(timezoneObject.format('TZH')).to.equal('-08'); + expect(timezoneObject.format('tzh')).to.equal('-08'); + expect(timezoneObject.format('TZM')).to.equal('00'); + expect(timezoneObject.format('tzm')).to.equal('00'); + + timezoneObject = new Timezone(new Date(Date.UTC(2017, 0, 1, 0, 0, 0)), 'America/St_Johns NDT'); + expect(timezoneObject.format('TZD')).to.equal('NDT'); + expect(timezoneObject.format('tzd')).to.equal('NDT'); + expect(timezoneObject.format('TZH')).to.equal('-03'); + expect(timezoneObject.format('tzh')).to.equal('-03'); + expect(timezoneObject.format('TZM')).to.equal('30'); + expect(timezoneObject.format('tzm')).to.equal('30'); + + + // 12. format combinations + const date = new Date(Date.UTC(2017, 3, 5, 13, 30, 30, 300)); + timezoneObject = new Timezone(date, timezone); + expect(timezoneObject.format('YYYY-MM-DD AM HH:MI:SS.FF')).to.equal('2017-04-05 PM 01:30:30.300'); + expect(timezoneObject.format('YYYY-MM-DD HH24:MI:SS.FF TZD')).to.equal('2017-04-05 13:30:30.300 KST'); + expect(timezoneObject.format('YYYY-MM-DD HH24:MI:SS.FF TZD TZH:TZM')).to.equal('2017-04-05 13:30:30.300 KST +09:00'); + expect(timezoneObject.format('CC Q DY, MON DD YYYY HH24:MI:SS.FF TZD TZH:TZM')).to.equal('21 2 Wed, Apr 05 2017 13:30:30.300 KST +09:00'); + }); + }); + + describe('toString', function() { + it('should success to validate the return values', function() { + const date = new Date(Date.UTC(2017, 3, 5, 13, 30, 30, 300)); + const timezone = 'Asia/Seoul KST'; + const timezoneObject = new Timezone(date, timezone); + expect(timezoneObject.toString()).to.equal('2017-04-05 13:30:30.300 Asia/Seoul KST') + }); + }); + + describe('valueOf', function() { + it('should success to validate the return values', function() { + let date = new Date(Date.UTC(2017, 3, 5, 13, 30, 30, 300)); + const timezone = 'Asia/Seoul KST'; + let timezoneObject = new Timezone(date, timezone); + expect(timezoneObject.valueOf()).to.equal(1491399030300); + + date = new Date(Date.UTC(2017, 10, 1, 20, 35, 40, 700)); + timezoneObject = new Timezone(date, timezone); + expect(timezoneObject.valueOf()).to.equal(1509568540700); + }); + }); + + describe('getOffset', function() { + it('should success to validate the return values', function() { + const date = new Date(Date.UTC(2017, 3, 5, 13, 30, 30, 300)); + let timezoneObject = new Timezone(date, 'Asia/Seoul KST'); + expect(timezoneObject.getOffset()).to.equal(-32400000); + + timezoneObject = new Timezone(date, 'UTC UTC'); + expect(timezoneObject.getOffset()).to.equal(0); + + timezoneObject = new Timezone(date, 'Europe/London BST'); + expect(timezoneObject.getOffset()).to.equal(-3600000); + + timezoneObject = new Timezone(date, 'America/Los_Angeles PDT'); + expect(timezoneObject.getOffset()).to.equal(25200000); + + timezoneObject = new Timezone(date, 'America/St_Johns NDT'); + expect(timezoneObject.getOffset()).to.equal(9000000); + }); + }); + + describe('with CUBRID', function() { + + it('should success to set Asia/Seoul in session', () => { + const client = testSetup.createDefaultCUBRIDDemodbConnection(); + + return client + .connect() + .then(() => { + return client.query(`SET SYSTEM PARAMETERS 'timezone=Asia/Seoul'`) + }) + .then(() => { + return client.query(`SELECT DATETIMELTZ'2017-11-11 11:11:11.111'`); + }) + .then(res => { + const value = res.result.ColumnValues[0][0]; + expect(value.timezone) + .to.equal('Asia/Seoul KST'); + }) + .then(() =>{ + return client.close(); + }); + }); + + it('should success to set Ameraca/Los_Angeles in session', () => { + const client = testSetup.createDefaultCUBRIDDemodbConnection(); + + return client + .connect() + .then(() => { + return client.query(`SET SYSTEM PARAMETERS 'timezone=America/Los_Angeles'`) + }) + .then(() => { + return client.query(`SELECT DATETIMELTZ'2017-11-11 11:11:11.111'`); + }) + .then(res => { + const value = res.result.ColumnValues[0][0]; + expect(value.timezone) + .to.equal('America/Los_Angeles PST'); + }) + .then(() =>{ + return client.close(); + }); + }); + + it('should success to set Europe/Zurich in session', () => { + const client = testSetup.createDefaultCUBRIDDemodbConnection(); + + return client + .connect() + .then(() => { + return client.query(`SET SYSTEM PARAMETERS 'timezone=Europe/Zurich'`) + }) + .then(() => { + return client.query(`SELECT DATETIMELTZ'2017-11-11 11:11:11.111'`); + }) + .then(res => { + const value = res.result.ColumnValues[0][0]; + expect(value.timezone) + .to.equal('Europe/Zurich CET'); + }) + .then(() =>{ + return client.close(); + }); + }); + + const TABLE_NAME = 'timezone_tbl'; + const TIMEZONE = 'Asia/Seoul'; + + beforeEach(testSetup.cleanup(TABLE_NAME)); + after(testSetup.cleanup(TABLE_NAME)); + + const createTable = `CREATE TABLE IF NOT EXISTS ${TABLE_NAME} (\ + col1 DATETIMETZ, col2 DATETIMELTZ, col3 TIMESTAMPTZ, col4 TIMESTAMPLTZ)`; + const insertData = `INSERT INTO ${TABLE_NAME} VALUES (\ + DATETIMETZ'2017-04-05 13:30:30.500 ${TIMEZONE}',\ + DATETIMELTZ'2017-04-05 13:30:30.500 ${TIMEZONE}',\ + TIMESTAMPTZ'2017-04-05 13:30:30 ${TIMEZONE}',\ + TIMESTAMPLTZ'2017-04-05 13:30:30 ${TIMEZONE}')`; + + it('should success to insert and select', () => { + const client = testSetup.createDefaultCUBRIDDemodbConnection(); + + return client + .connect() + .then(() => { + return client.query(`SET SYSTEM PARAMETERS 'timezone=${TIMEZONE}'`) + }) + .then(() => { + return client.execute(createTable); + }) + .then(() => { + return client.execute(insertData); + }) + .then(() => { + // Testing DATETIMETZ and TIMESTAMPTZ + return client.query(`SELECT col1, col3 FROM ${TABLE_NAME}`); + }) + .then(res => { + const result = res.result; + + // This test should be fail because server respond invalid data type + // const datetimetz = result.ColumnDataTypes[0]; + // const timestamptz = result.ColumnDataTypes[0]; + // + // expect(datetimetz) + // .to.equal(CAS.getCUBRIDDataTypeName(CAS.CUBRIDDataType.CCI_U_TYPE_DATETIMETZ)); + // expect(timestamptz) + // .to.equal(CAS.getCUBRIDDataTypeName(CAS.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPTZ)); + + const row = result.ColumnValues[0]; + const col1 = row[0].toString(); + const col2 = row[1].toString(); + + expect(col1) + .to.equal('2017-04-05 13:30:30.500 Asia/Seoul KST'); + expect(col2) + .to.equal('2017-04-05 13:30:30.000 Asia/Seoul KST'); + }) + .then(() =>{ + return client.close(); + }) + .then(() => { + return client.connect(); + }) + .then(() => { + return client.query(`SET SYSTEM PARAMETERS 'timezone=America/Los_Angeles'`); + }) + .then(() => { + // Testing DATETIMELTZ and TIMESTAMPLTZ + return client.query(`SELECT col2, col4 FROM ${TABLE_NAME}`) + }) + .then(res => { + const result = res.result; + + // This test should be fail because server respond invalid data type + // const datetimeltz = result.ColumnDataTypes[0]; + // const timestampltz = result.ColumnDataTypes[0]; + // + // expect(datetimeltz) + // .to.equal(CAS.getCUBRIDDataTypeName(CAS.CUBRIDDataType.CCI_U_TYPE_DATETIMELTZ)); + // expect(timestampltz) + // .to.equal(CAS.getCUBRIDDataTypeName(CAS.CUBRIDDataType.CCI_U_TYPE_TIMESTAMPLTZ)); + + const row = result.ColumnValues[0]; + const col2 = row[0].toString(); + const col4 = row[1].toString(); + + expect(col2) + .to.equal('2017-04-04 21:30:30.500 America/Los_Angeles PDT'); + expect(col4) + .to.equal('2017-04-04 21:30:30.000 America/Los_Angeles PDT'); + }) + .then(() =>{ + return client.close(); + }); + }); + }); +});