From 7219962f0cbf8e167ca82e138874483c234cf33b Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Sun, 3 May 2020 22:35:24 +0200 Subject: [PATCH] Improved timezone handling --- config.php | 1 + debian/changelog | 2 +- js/db/connection.js | 49 ++++++++++++------------------ js/htk/style.css | 4 +++ js/sql/value.js | 74 ++++++++++++++++++++------------------------- package.json | 2 +- rest/core/query.php | 32 +++++++++++++------- 7 files changed, 80 insertions(+), 84 deletions(-) diff --git a/config.php b/config.php index ba53d09c..bca8a8db 100644 --- a/config.php +++ b/config.php @@ -23,5 +23,6 @@ return [ ,'schema' => 'hedera' ,'user' => 'hedera-web' ,'pass' => '' + ,'tz' => 'Europe/madrid' ] ]; diff --git a/debian/changelog b/debian/changelog index ff0bcb60..51ba36fa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -hedera-web (1.407.11) stable; urgency=low +hedera-web (1.407.12) stable; urgency=low * Initial Release. diff --git a/js/db/connection.js b/js/db/connection.js index be4785cc..8b440468 100644 --- a/js/db/connection.js +++ b/js/db/connection.js @@ -9,7 +9,7 @@ * class or you could have a serious security hole in you application becasuse * the user can send any statement to the server. For example: DROP DATABASE **/ -var Connection = new Class (); +var Connection = new Class(); module.exports = Connection; var Flag = @@ -45,10 +45,9 @@ Connection.implement * @param {String} sql The SQL statement * @param {Function} callback The function to call when operation is done **/ - ,execSql: function (sql, callback) - { - this.send ('core/query', {'sql': sql}, - this._onExec.bind (this, callback)); + ,execSql: function(sql, callback) { + this.send('core/query', {'sql': sql}, + this._onExec.bind(this, callback)); } /** @@ -58,9 +57,8 @@ Connection.implement * @param {Function} callback The function to call when operation is done * @param {Sql.Batch} batch The batch used to set the parameters **/ - ,execStmt: function (stmt, callback, batch) - { - this.execSql (stmt.render (batch), callback); + ,execStmt: function(stmt, callback, batch) { + this.execSql(stmt.render(batch), callback); } /** @@ -70,39 +68,33 @@ Connection.implement * @param {Function} callback The function to call when operation is done * @param {Sql.Batch} batch The batch used to set the parameters **/ - ,execQuery: function (query, callback, batch) - { - this.execStmt (new Sql.String ({query: query}), callback, batch); + ,execQuery: function(query, callback, batch) { + this.execStmt(new Sql.String({query: query}), callback, batch); } /* * Parses a value to date. */ - ,valueToDate: function (value) - { - return new Date (value * 1000); + ,valueToDate: function(value) { + return new Date(value); } /* * Called when a query is executed. */ - ,_onExec: function (callback, json, error) - { + ,_onExec: function(callback, json, error) { if (json) try { if (json && json instanceof Array) for (var i = 0; i < json.length; i++) - if (json[i] !== true) - { + if (json[i] !== true) { var data = json[i].data; var columns = json[i].columns; - for (var j = 0; j < columns.length; j++) - { + for (var j = 0; j < columns.length; j++) { var castFunc = null; - switch (columns[j].type) - { + switch (columns[j].type) { case Type.DATE: case Type.DATE_TIME: case Type.TIMESTAMP: @@ -110,25 +102,22 @@ Connection.implement break; } - if (castFunc !== null) - { + if (castFunc !== null) { if (columns[j].def != null) - columns[j].def = castFunc (columns[j].def); + columns[j].def = castFunc(columns[j].def); for (var k = 0; k < data.length; k++) if (data[k][j] != null) - data[k][j] = castFunc (data[k][j]); + data[k][j] = castFunc(data[k][j]); } } } - } - catch (e) - { + } catch (e) { error = e; } if (callback) - callback (new Db.ResultSet (json, error)); + callback(new Db.ResultSet(json, error)); } }); diff --git a/js/htk/style.css b/js/htk/style.css index b8612dfa..cc3676f4 100644 --- a/js/htk/style.css +++ b/js/htk/style.css @@ -235,6 +235,10 @@ td.cell-image .htk-image { border-top: none; } +.htk-calendar th.button +{ + display: table-cell; +} .htk-calendar th.button:hover { cursor: pointer; diff --git a/js/sql/value.js b/js/sql/value.js index fa86052e..3460f42d 100644 --- a/js/sql/value.js +++ b/js/sql/value.js @@ -1,11 +1,10 @@ -var Expr = require ('./expr'); +var Expr = require('./expr'); /** * The equivalent of a SQL value. **/ -module.exports = new Class -({ +module.exports = new Class({ Extends: Expr ,Tag: 'sql-value' @@ -17,13 +16,11 @@ module.exports = new Class param: { type: Vn.Param - ,set: function (x) - { - this.link ({_param: x}, {'changed': this.onParamChange}); - this.onParamChange (); + ,set: function(x) { + this.link({_param: x}, {'changed': this.onParamChange}); + this.onParamChange(); } - ,get: function () - { + ,get: function() { return this._param; } }, @@ -33,27 +30,24 @@ module.exports = new Class value: { type: String - ,set: function (x) - { - if (Vn.Value.compare (x, this._value)) + ,set: function(x) { + if (Vn.Value.compare(x, this._value)) return; if (x instanceof Date) - x = x.clone (); + x = x.clone(); this._value = x; - if (this._param && !this.paramLock) - { + if (this._param && !this.paramLock) { this.paramLock = true; this._param.value = x; this.paramLock = false; } - this.signalEmit ('changed'); + this.signalEmit('changed'); } - ,get: function () - { + ,get: function() { return this._value; } } @@ -61,11 +55,10 @@ module.exports = new Class ,_value: undefined ,_param: null - ,regexp: new RegExp ('(\\\\)|\'', 'g') + ,regexp: new RegExp('(\\\\)|\'', 'g') ,paramLock: false - ,onParamChange: function () - { + ,onParamChange: function() { if (this.paramLock || !this._param) return; @@ -74,15 +67,12 @@ module.exports = new Class this.paramLock = false; } - ,isReady: function () - { + ,isReady: function() { return this._value !== undefined; } - ,replaceFunc: function (token) - { - switch (token) - { + ,replaceFunc: function(token) { + switch (token) { case '\\': return '\\\\'; case '\'': return '\\\''; } @@ -90,23 +80,25 @@ module.exports = new Class return token; } - ,render: function (batch) - { + ,render: function() { var v = this._value; - switch (typeof v) - { - case 'number': - return v; - case 'boolean': - return (v) ? 'TRUE' : 'FALSE'; - case 'string': - return "'" + v.replace (this.regexp, this.replaceFunc) + "'"; - case 'object': - if (v instanceof Date) - return Vn.Date.strftime (v, '\'%Y-%m-%d\''); - default: + switch (typeof v) { + case 'number': + return v; + case 'boolean': + return (v) ? 'TRUE' : 'FALSE'; + case 'string': + return "'" + v.replace(this.regexp, this.replaceFunc) + "'"; + default: + if (v instanceof Date) { + // TODO: Read time zone from db configuration + var tz = {timeZone: 'Europe/Madrid'}; + var localeDate = new Date(v.toLocaleString('en-US', tz)); + return Vn.Date.strftime(localeDate, '\'%Y-%m-%d\''); + } else { return 'NULL'; + } } } }); diff --git a/package.json b/package.json index 34f4635d..91e00da1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hedera-web", - "version": "1.407.11", + "version": "1.407.12", "description": "Verdnatura web page", "license": "GPL-3.0", "repository": { diff --git a/rest/core/query.php b/rest/core/query.php index 2ba22780..998e1d5a 100644 --- a/rest/core/query.php +++ b/rest/core/query.php @@ -8,6 +8,18 @@ class Query extends Vn\Web\JsonRequest { const PARAMS = ['sql']; const SECURITY = Security::INVOKER; + function __construct($app) { + parent::__construct($app); + $this->utcTz = new DateTimeZone('UTC'); + + $dbConf = $app->getConf()['db']; + + if (isset($dbConf['tz'])) + $this->tz = new DateTimeZone($dbConf['tz']); + else + $this->tz = $this->utcTz; + } + function run($db) { $results = []; @@ -151,7 +163,10 @@ class Query extends Vn\Web\JsonRequest { * Transforms the database value into a JSON parseable value. **/ function castValue($value, $type) { - if ($value !== NULL) + if ($value == '' && $type != Type::STRING) + $value = NULL; + + if (!empty($value)) switch ($type) { case Type::BOOLEAN: return (bool) $value; @@ -159,16 +174,11 @@ class Query extends Vn\Web\JsonRequest { return (int) $value; case Type::DOUBLE: return (float) $value; - case Type::DATE: - case Type::DATE_TIME: - return mktime( - substr($value, 11 , 2) - ,substr($value, 14 , 2) - ,substr($value, 17 , 2) - ,substr($value, 5 , 2) - ,substr($value, 8 , 2) - ,substr($value, 0 , 4) - ); + case Type::DATE: + case Type::DATE_TIME: + $d = new DateTime($value, $this->tz); + $d->setTimeZone($this->utcTz); + return $d->format('Y-m-d\TH:i:s.v\Z'); break; }