forked from verdnatura/hedera-web
Improved timezone handling
This commit is contained in:
parent
4733185e9f
commit
7219962f0c
|
@ -23,5 +23,6 @@ return [
|
||||||
,'schema' => 'hedera'
|
,'schema' => 'hedera'
|
||||||
,'user' => 'hedera-web'
|
,'user' => 'hedera-web'
|
||||||
,'pass' => ''
|
,'pass' => ''
|
||||||
|
,'tz' => 'Europe/madrid'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
hedera-web (1.407.11) stable; urgency=low
|
hedera-web (1.407.12) stable; urgency=low
|
||||||
|
|
||||||
* Initial Release.
|
* Initial Release.
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
* class or you could have a serious security hole in you application becasuse
|
* 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
|
* the user can send any statement to the server. For example: DROP DATABASE
|
||||||
**/
|
**/
|
||||||
var Connection = new Class ();
|
var Connection = new Class();
|
||||||
module.exports = Connection;
|
module.exports = Connection;
|
||||||
|
|
||||||
var Flag =
|
var Flag =
|
||||||
|
@ -45,10 +45,9 @@ Connection.implement
|
||||||
* @param {String} sql The SQL statement
|
* @param {String} sql The SQL statement
|
||||||
* @param {Function} callback The function to call when operation is done
|
* @param {Function} callback The function to call when operation is done
|
||||||
**/
|
**/
|
||||||
,execSql: function (sql, callback)
|
,execSql: function(sql, callback) {
|
||||||
{
|
this.send('core/query', {'sql': sql},
|
||||||
this.send ('core/query', {'sql': sql},
|
this._onExec.bind(this, callback));
|
||||||
this._onExec.bind (this, callback));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,9 +57,8 @@ Connection.implement
|
||||||
* @param {Function} callback The function to call when operation is done
|
* @param {Function} callback The function to call when operation is done
|
||||||
* @param {Sql.Batch} batch The batch used to set the parameters
|
* @param {Sql.Batch} batch The batch used to set the parameters
|
||||||
**/
|
**/
|
||||||
,execStmt: function (stmt, callback, batch)
|
,execStmt: function(stmt, callback, batch) {
|
||||||
{
|
this.execSql(stmt.render(batch), callback);
|
||||||
this.execSql (stmt.render (batch), callback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,39 +68,33 @@ Connection.implement
|
||||||
* @param {Function} callback The function to call when operation is done
|
* @param {Function} callback The function to call when operation is done
|
||||||
* @param {Sql.Batch} batch The batch used to set the parameters
|
* @param {Sql.Batch} batch The batch used to set the parameters
|
||||||
**/
|
**/
|
||||||
,execQuery: function (query, callback, batch)
|
,execQuery: function(query, callback, batch) {
|
||||||
{
|
this.execStmt(new Sql.String({query: query}), callback, batch);
|
||||||
this.execStmt (new Sql.String ({query: query}), callback, batch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parses a value to date.
|
* Parses a value to date.
|
||||||
*/
|
*/
|
||||||
,valueToDate: function (value)
|
,valueToDate: function(value) {
|
||||||
{
|
return new Date(value);
|
||||||
return new Date (value * 1000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when a query is executed.
|
* Called when a query is executed.
|
||||||
*/
|
*/
|
||||||
,_onExec: function (callback, json, error)
|
,_onExec: function(callback, json, error) {
|
||||||
{
|
|
||||||
if (json)
|
if (json)
|
||||||
try {
|
try {
|
||||||
if (json && json instanceof Array)
|
if (json && json instanceof Array)
|
||||||
for (var i = 0; i < json.length; i++)
|
for (var i = 0; i < json.length; i++)
|
||||||
if (json[i] !== true)
|
if (json[i] !== true) {
|
||||||
{
|
|
||||||
var data = json[i].data;
|
var data = json[i].data;
|
||||||
var columns = json[i].columns;
|
var columns = json[i].columns;
|
||||||
|
|
||||||
for (var j = 0; j < columns.length; j++)
|
for (var j = 0; j < columns.length; j++) {
|
||||||
{
|
|
||||||
var castFunc = null;
|
var castFunc = null;
|
||||||
|
|
||||||
switch (columns[j].type)
|
switch (columns[j].type) {
|
||||||
{
|
|
||||||
case Type.DATE:
|
case Type.DATE:
|
||||||
case Type.DATE_TIME:
|
case Type.DATE_TIME:
|
||||||
case Type.TIMESTAMP:
|
case Type.TIMESTAMP:
|
||||||
|
@ -110,25 +102,22 @@ Connection.implement
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (castFunc !== null)
|
if (castFunc !== null) {
|
||||||
{
|
|
||||||
if (columns[j].def != 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++)
|
for (var k = 0; k < data.length; k++)
|
||||||
if (data[k][j] != null)
|
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;
|
error = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback)
|
if (callback)
|
||||||
callback (new Db.ResultSet (json, error));
|
callback(new Db.ResultSet(json, error));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -235,6 +235,10 @@ td.cell-image .htk-image
|
||||||
{
|
{
|
||||||
border-top: none;
|
border-top: none;
|
||||||
}
|
}
|
||||||
|
.htk-calendar th.button
|
||||||
|
{
|
||||||
|
display: table-cell;
|
||||||
|
}
|
||||||
.htk-calendar th.button:hover
|
.htk-calendar th.button:hover
|
||||||
{
|
{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
|
|
||||||
var Expr = require ('./expr');
|
var Expr = require('./expr');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The equivalent of a SQL value.
|
* The equivalent of a SQL value.
|
||||||
**/
|
**/
|
||||||
module.exports = new Class
|
module.exports = new Class({
|
||||||
({
|
|
||||||
Extends: Expr
|
Extends: Expr
|
||||||
,Tag: 'sql-value'
|
,Tag: 'sql-value'
|
||||||
|
|
||||||
|
@ -17,13 +16,11 @@ module.exports = new Class
|
||||||
param:
|
param:
|
||||||
{
|
{
|
||||||
type: Vn.Param
|
type: Vn.Param
|
||||||
,set: function (x)
|
,set: function(x) {
|
||||||
{
|
this.link({_param: x}, {'changed': this.onParamChange});
|
||||||
this.link ({_param: x}, {'changed': this.onParamChange});
|
this.onParamChange();
|
||||||
this.onParamChange ();
|
|
||||||
}
|
}
|
||||||
,get: function ()
|
,get: function() {
|
||||||
{
|
|
||||||
return this._param;
|
return this._param;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -33,27 +30,24 @@ module.exports = new Class
|
||||||
value:
|
value:
|
||||||
{
|
{
|
||||||
type: String
|
type: String
|
||||||
,set: function (x)
|
,set: function(x) {
|
||||||
{
|
if (Vn.Value.compare(x, this._value))
|
||||||
if (Vn.Value.compare (x, this._value))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (x instanceof Date)
|
if (x instanceof Date)
|
||||||
x = x.clone ();
|
x = x.clone();
|
||||||
|
|
||||||
this._value = x;
|
this._value = x;
|
||||||
|
|
||||||
if (this._param && !this.paramLock)
|
if (this._param && !this.paramLock) {
|
||||||
{
|
|
||||||
this.paramLock = true;
|
this.paramLock = true;
|
||||||
this._param.value = x;
|
this._param.value = x;
|
||||||
this.paramLock = false;
|
this.paramLock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.signalEmit ('changed');
|
this.signalEmit('changed');
|
||||||
}
|
}
|
||||||
,get: function ()
|
,get: function() {
|
||||||
{
|
|
||||||
return this._value;
|
return this._value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,11 +55,10 @@ module.exports = new Class
|
||||||
|
|
||||||
,_value: undefined
|
,_value: undefined
|
||||||
,_param: null
|
,_param: null
|
||||||
,regexp: new RegExp ('(\\\\)|\'', 'g')
|
,regexp: new RegExp('(\\\\)|\'', 'g')
|
||||||
,paramLock: false
|
,paramLock: false
|
||||||
|
|
||||||
,onParamChange: function ()
|
,onParamChange: function() {
|
||||||
{
|
|
||||||
if (this.paramLock || !this._param)
|
if (this.paramLock || !this._param)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -74,15 +67,12 @@ module.exports = new Class
|
||||||
this.paramLock = false;
|
this.paramLock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
,isReady: function ()
|
,isReady: function() {
|
||||||
{
|
|
||||||
return this._value !== undefined;
|
return this._value !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
,replaceFunc: function (token)
|
,replaceFunc: function(token) {
|
||||||
{
|
switch (token) {
|
||||||
switch (token)
|
|
||||||
{
|
|
||||||
case '\\': return '\\\\';
|
case '\\': return '\\\\';
|
||||||
case '\'': return '\\\'';
|
case '\'': return '\\\'';
|
||||||
}
|
}
|
||||||
|
@ -90,23 +80,25 @@ module.exports = new Class
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
,render: function (batch)
|
,render: function() {
|
||||||
{
|
|
||||||
var v = this._value;
|
var v = this._value;
|
||||||
|
|
||||||
switch (typeof v)
|
switch (typeof v) {
|
||||||
{
|
|
||||||
case 'number':
|
case 'number':
|
||||||
return v;
|
return v;
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
return (v) ? 'TRUE' : 'FALSE';
|
return (v) ? 'TRUE' : 'FALSE';
|
||||||
case 'string':
|
case 'string':
|
||||||
return "'" + v.replace (this.regexp, this.replaceFunc) + "'";
|
return "'" + v.replace(this.regexp, this.replaceFunc) + "'";
|
||||||
case 'object':
|
|
||||||
if (v instanceof Date)
|
|
||||||
return Vn.Date.strftime (v, '\'%Y-%m-%d\'');
|
|
||||||
default:
|
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';
|
return 'NULL';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "hedera-web",
|
"name": "hedera-web",
|
||||||
"version": "1.407.11",
|
"version": "1.407.12",
|
||||||
"description": "Verdnatura web page",
|
"description": "Verdnatura web page",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -8,6 +8,18 @@ class Query extends Vn\Web\JsonRequest {
|
||||||
const PARAMS = ['sql'];
|
const PARAMS = ['sql'];
|
||||||
const SECURITY = Security::INVOKER;
|
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) {
|
function run($db) {
|
||||||
$results = [];
|
$results = [];
|
||||||
|
|
||||||
|
@ -151,7 +163,10 @@ class Query extends Vn\Web\JsonRequest {
|
||||||
* Transforms the database value into a JSON parseable value.
|
* Transforms the database value into a JSON parseable value.
|
||||||
**/
|
**/
|
||||||
function castValue($value, $type) {
|
function castValue($value, $type) {
|
||||||
if ($value !== NULL)
|
if ($value == '' && $type != Type::STRING)
|
||||||
|
$value = NULL;
|
||||||
|
|
||||||
|
if (!empty($value))
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case Type::BOOLEAN:
|
case Type::BOOLEAN:
|
||||||
return (bool) $value;
|
return (bool) $value;
|
||||||
|
@ -161,14 +176,9 @@ class Query extends Vn\Web\JsonRequest {
|
||||||
return (float) $value;
|
return (float) $value;
|
||||||
case Type::DATE:
|
case Type::DATE:
|
||||||
case Type::DATE_TIME:
|
case Type::DATE_TIME:
|
||||||
return mktime(
|
$d = new DateTime($value, $this->tz);
|
||||||
substr($value, 11 , 2)
|
$d->setTimeZone($this->utcTz);
|
||||||
,substr($value, 14 , 2)
|
return $d->format('Y-m-d\TH:i:s.v\Z');
|
||||||
,substr($value, 17 , 2)
|
|
||||||
,substr($value, 5 , 2)
|
|
||||||
,substr($value, 8 , 2)
|
|
||||||
,substr($value, 0 , 4)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue