From 54966582b51cbc5ed6710f2f32b64b0529a6af96 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Mon, 4 May 2020 21:55:18 +0200 Subject: [PATCH] Timezone fixes --- debian/changelog | 2 +- forms/ecomerce/checkout/checkout.js | 4 +- js/db/connection.js | 31 +++- js/htk/field/calendar.js | 242 +++++++++++++--------------- js/sql/value.js | 19 ++- js/vn/date.js | 54 +++---- package.json | 2 +- rest/core/query.php | 4 +- 8 files changed, 184 insertions(+), 174 deletions(-) diff --git a/debian/changelog b/debian/changelog index 51ba36fa..be146066 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -hedera-web (1.407.12) stable; urgency=low +hedera-web (1.407.13) stable; urgency=low * Initial Release. diff --git a/forms/ecomerce/checkout/checkout.js b/forms/ecomerce/checkout/checkout.js index 1a9ea7bf..216a5e38 100644 --- a/forms/ecomerce/checkout/checkout.js +++ b/forms/ecomerce/checkout/checkout.js @@ -27,6 +27,8 @@ Hedera.Checkout = new Class({ if (!date || date.getTime() < (new Date()).getTime()) { date = new Date(); + date.setHours(0, 0, 0, 0); + var addDays = 0; switch(date.getDay()) { @@ -41,7 +43,7 @@ Hedera.Checkout = new Class({ if (i.get('deliveryMethod') != 'PICKUP') addDays++; - date.setTime(date.getTime() + addDays * 86400000); + date.setDate(date.getDate() + addDays); } this.$('date').value = date; diff --git a/js/db/connection.js b/js/db/connection.js index 8b440468..e2b96987 100644 --- a/js/db/connection.js +++ b/js/db/connection.js @@ -29,14 +29,12 @@ var Type = ,DATE_TIME : 9 }; -Connection.extend -({ +Connection.extend({ Flag: Flag ,Type: Type }); -Connection.implement -({ +Connection.implement({ Extends: Vn.JsonConnection /** @@ -76,7 +74,7 @@ Connection.implement * Parses a value to date. */ ,valueToDate: function(value) { - return new Date(value); + return fixTz(new Date(value)); } /* @@ -121,3 +119,26 @@ Connection.implement } }); +// TODO: Read time zone from db configuration +var tz = {timeZone: 'Europe/Madrid'}; +var isLocal = Intl + .DateTimeFormat() + .resolvedOptions() + .timeZone == tz.timeZone; + +function fixTz(date) { + if (isLocal) return date; + + var localDate = new Date(date.toLocaleString('en-US', tz)); + var hasTime = localDate.getHours() + || localDate.getMinutes() + || localDate.getSeconds() + || localDate.getMilliseconds(); + + if (!hasTime) { + date.setHours(date.getHours() + 12); + date.setHours(0, 0, 0, 0); + } + + return date; +} diff --git a/js/htk/field/calendar.js b/js/htk/field/calendar.js index 82e223f1..c024feb6 100644 --- a/js/htk/field/calendar.js +++ b/js/htk/field/calendar.js @@ -1,6 +1,5 @@ -module.exports = new Class -({ +module.exports = new Class({ Extends: Htk.Field ,Tag: 'htk-calendar' ,Properties: @@ -8,12 +7,10 @@ module.exports = new Class restrictFunc: { type: Function - ,set: function (x) - { + ,set: function(x) { this._restrictFunc = x; } - ,get: function (x) - { + ,get: function(x) { return this._restrictFunc; } } @@ -24,83 +21,79 @@ module.exports = new Class ,year: null ,month: null - ,render: function () - { + ,render: function() { var len = Vn.Date.WDays.length; - var node = this.createRoot ('div'); + var node = this.createRoot('div'); node.className = 'htk-calendar'; - var table = this.createElement ('table'); - this.node.appendChild (table); + var table = this.createElement('table'); + this.node.appendChild(table); - var colgroup = this.createElement ('colgroup'); - table.appendChild (colgroup); + var colgroup = this.createElement('colgroup'); + table.appendChild(colgroup); for (var i = 0; i < len; i++) - colgroup.appendChild (this.createElement ('col')); + colgroup.appendChild(this.createElement('col')); - var thead = this.createElement ('thead'); - table.appendChild (thead); + var thead = this.createElement('thead'); + table.appendChild(thead); - var tr = this.createElement ('tr'); - thead.appendChild (tr); + var tr = this.createElement('tr'); + thead.appendChild(tr); - var th = this.createElement ('th'); - th.appendChild (this.createTextNode ('<')); + var th = this.createElement('th'); + th.appendChild(this.createTextNode('<')); th.className = 'button'; - th.addEventListener ('click', this.prevMonthClicked.bind (this)); - tr.appendChild (th); + th.addEventListener('click', this.prevMonthClicked.bind(this)); + tr.appendChild(th); - var th = this.createElement ('th'); + var th = this.createElement('th'); th.colSpan = 5; - tr.appendChild (th); + tr.appendChild(th); - var monthNode = this.createElement ('span'); - th.appendChild (monthNode); + var monthNode = this.createElement('span'); + th.appendChild(monthNode); - var space = this.createTextNode (' '); - th.appendChild (space); + var space = this.createTextNode(' '); + th.appendChild(space); - var yearNode = this.createElement ('span'); - th.appendChild (yearNode); + var yearNode = this.createElement('span'); + th.appendChild(yearNode); - var th = this.createElement ('th'); - th.appendChild (this.createTextNode ('>')); + var th = this.createElement('th'); + th.appendChild(this.createTextNode('>')); th.className = 'button'; - th.addEventListener ('click', this.nextMonthClicked.bind (this)); - tr.appendChild (th); + th.addEventListener('click', this.nextMonthClicked.bind(this)); + tr.appendChild(th); - var tr = this.createElement ('tr'); - thead.appendChild (tr); + var tr = this.createElement('tr'); + thead.appendChild(tr); - for (var i = 1; i <= len; i++) - { - var th = this.createElement ('th'); - tr.appendChild (th); + for (var i = 1; i <= len; i++) { + var th = this.createElement('th'); + tr.appendChild(th); var weekday = _(Vn.Date.AbrWDays [i%len]); - th.appendChild (this.createTextNode (weekday)); + th.appendChild(this.createTextNode(weekday)); } - var tbody = this.createElement ('tbody'); - table.appendChild (tbody); + var tbody = this.createElement('tbody'); + table.appendChild(tbody); - for (var i = 0; i < 6; i++) - { - var tr = this.createElement ('tr'); - tbody.appendChild (tr); + for (var i = 0; i < 6; i++) { + var tr = this.createElement('tr'); + tbody.appendChild(tr); - for (var j = 0; j < len; j++) - { - var td = this.createElement ('td'); - td.addEventListener ('click', this.dayClicked.bind (this, td, i*len+j)); - tr.appendChild (td); + for (var j = 0; j < len; j++) { + var td = this.createElement('td'); + td.addEventListener('click', this.dayClicked.bind(this, td, i*len+j)); + tr.appendChild(td); - var div = this.createElement ('div'); - td.appendChild (div); + var div = this.createElement('div'); + td.appendChild(div); - this.cells.push ({ + this.cells.push({ node: div, enabled: false, day: -1 @@ -110,11 +103,10 @@ module.exports = new Class this.monthNode = monthNode; this.yearNode = yearNode; - this.goToCurrentMonth (); + this.goToCurrentMonth(); } - ,getMonthDays: function () - { + ,getMonthDays: function() { if (this.month > 6) return (this.month % 2 != 0) ? 31 : 30; else if (this.month != 1) @@ -123,63 +115,54 @@ module.exports = new Class return (this.year % 4 != 0) ? 28 : 29; } - ,goToMonth: function (year, month) - { + ,goToMonth: function(year, month) { if (year) this.year = year; - if (!isNaN (month)) + if (!isNaN(month)) this.month = month; - this.refresh (); + this.refresh(); } - ,goToSelectedMonth: function () - { + ,goToSelectedMonth: function() { var date = this._value; if (date instanceof Date) - this.goToMonth (date.getFullYear (), date.getMonth ()); + this.goToMonth(date.getFullYear(), date.getMonth()); else - this.goToCurrentMonth (); + this.goToCurrentMonth(); } - ,goToCurrentMonth: function () - { - var date = new Date (); - this.goToMonth (date.getFullYear (), date.getMonth ()); + ,goToCurrentMonth: function() { + var date = new Date(); + this.goToMonth(date.getFullYear(), date.getMonth()); } - ,refresh: function () - { - Vn.Node.setText (this.yearNode, this.year); - Vn.Node.setText (this.monthNode, _(Vn.Date.Months[this.month])); + ,refresh: function() { + Vn.Node.setText(this.yearNode, this.year); + Vn.Node.setText(this.monthNode, _(Vn.Date.Months[this.month])); var day = 1; - var cellDate = new Date (this.year, this.month, 1); + var cellDate = new Date(this.year, this.month, 1); - var weekDay = cellDate.getDay (); + var weekDay = cellDate.getDay(); var firstWeekDay = (weekDay != 0) ? weekDay - 1 : 6; - var monthDays = this.getMonthDays (); + var monthDays = this.getMonthDays(); - for (var i = 0; i < this.cells.length; i++) - { + for (var i = 0; i < this.cells.length; i++) { var cell = this.cells[i]; - if (firstWeekDay <= i && day <= monthDays) - { - Vn.Node.setText (cell.node, day); + if (firstWeekDay <= i && day <= monthDays) { + Vn.Node.setText(cell.node, day); cell.enabled = true; cell.day = day++; - if (this._restrictFunc) - { - cell.enabled = this._restrictFunc (cellDate); - cellDate.setDate (cellDate.getDate () + 1); + if (this._restrictFunc) { + cell.enabled = this._restrictFunc(cellDate); + cellDate.setDate(cellDate.getDate() + 1); } - } - else - { - Vn.Node.removeChilds (cell.node); + } else { + Vn.Node.removeChilds(cell.node); cell.enabled = false; cell.day = -1; } @@ -189,13 +172,12 @@ module.exports = new Class // Marks the current day - var today = new Date (); + var today = new Date(); - if (this.year == today.getFullYear () - && this.month == today.getMonth ()) - { - var cellIndex = (firstWeekDay + today.getDate ()) - 1; - Vn.Node.addClass (this.cells[cellIndex].node, 'today'); + if (this.year == today.getFullYear() + && this.month == today.getMonth()) { + var cellIndex = (firstWeekDay + today.getDate()) - 1; + Vn.Node.addClass(this.cells[cellIndex].node, 'today'); } // Marks the selected day @@ -203,70 +185,74 @@ module.exports = new Class var date = this._value; if (date instanceof Date - && this.year == date.getFullYear () - && this.month == date.getMonth ()) - this.selectCell ((firstWeekDay + date.getDate ()) - 1); + && this.year == date.getFullYear() + && this.month == date.getMonth()) + this.selectCell((firstWeekDay + date.getDate()) - 1); else - this.selectCell (-1); + this.selectCell(-1); } - ,selectCell: function (cellIndex) - { - if (this.selectedCell != -1) - { + ,selectCell: function(cellIndex) { + if (this.selectedCell != -1) { var node = this.cells[this.selectedCell].node; - Vn.Node.removeClass (node, 'selected'); + Vn.Node.removeClass(node, 'selected'); } - if (cellIndex != -1) - { + if (cellIndex != -1) { var node = this.cells[cellIndex].node; - Vn.Node.addClass (node, 'selected'); + Vn.Node.addClass(node, 'selected'); } this.selectedCell = cellIndex; } - ,putValue: function (value) - { - this.goToSelectedMonth (); + ,putValue: function() { + this.goToSelectedMonth(); } - ,dayClicked: function (td, cellIndex) - { + ,dayClicked: function(td, cellIndex) { var cell = this.cells[cellIndex]; - if (cell.enabled) - { - this.selectCell (cellIndex); + if (cell.enabled) { + this.selectCell(cellIndex); - var newDate = new Date (this.year, this.month, cell.day); - this.valueChanged (newDate); + var newDate = new Date(this.year, this.month, cell.day); + + if (this.value) { + var orgDate = this.value instanceof Date + ? this.value + : new Date(this.value); + + newDate.setHours( + orgDate.getHours(), + orgDate.getMinutes(), + orgDate.getSeconds(), + orgDate.getMilliseconds() + ); + } + + this.valueChanged(newDate); } } - ,prevMonthClicked: function () - { + ,prevMonthClicked: function() { if (this.month > 0) this.month--; - else - { + else { this.month = 11; this.year--; } - this.refresh (); + this.refresh(); } - ,nextMonthClicked: function () - { + ,nextMonthClicked: function() { if (this.month < 11) this.month++; - else - { + else { this.month = 0; this.year++; } - this.refresh (); + this.refresh(); } }); diff --git a/js/sql/value.js b/js/sql/value.js index 3460f42d..41e7ab64 100644 --- a/js/sql/value.js +++ b/js/sql/value.js @@ -91,14 +91,19 @@ module.exports = new Class({ 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 { + if (v instanceof Date) + return Vn.Date.strftime(fixTz(v), '\'%Y-%m-%d\''); + else return 'NULL'; - } } } }); + +function fixTz(date) { + var midDay = new Date(date.getTime()); + midDay.setHours(12, 0, 0, 0); + + // TODO: Read time zone from db configuration + var tz = {timeZone: 'Europe/Madrid'}; + return new Date(midDay.toLocaleString('en-US', tz)); +} diff --git a/js/vn/date.js b/js/vn/date.js index 78691d87..f57aaacd 100644 --- a/js/vn/date.js +++ b/js/vn/date.js @@ -2,14 +2,13 @@ * Date handling utilities. **/ -Date.prototype.clone = function () -{ - return new Date (this.getTime ()); +Date.prototype.clone = function() { + return new Date(this.getTime()); } module.exports = { - WDays: + WDays: [ 'Sunday' ,'Monday' @@ -62,66 +61,63 @@ module.exports = ,tokenD: '%A, %B %e' - ,regexp: new RegExp ('%[a-zA-Z]', 'g') + ,regexp: new RegExp('%[a-zA-Z]', 'g') - ,pad: function (number) - { + ,pad: function(number) { if (number < 10) - return '0'+ number.toString (); + return '0'+ number.toString(); - return number.toString (); + return number.toString(); } - ,regexpFunc: function (d, token) - { - switch (token.charAt (1)) - { + ,regexpFunc: function(d, token) { + switch (token.charAt(1)) { // Minutes with 2 digits - case 'M': return this.pad (d.getMinutes ()); + case 'M': return this.pad(d.getMinutes()); // Hour with 2 digits in 24 hour format - case 'H': return this.pad (d.getHours ()); + case 'H': return this.pad(d.getHours()); // Complete time - case 'T': return d.toLocaleTimeString (); + case 'T': return d.toLocaleTimeString(); // Complete week day name - case 'A': return _(this.WDays[d.getDay ()]); + case 'A': return _(this.WDays[d.getDay()]); // Abreviated week day name - case 'a': return _(this.AbrWDays[d.getDay ()]); + case 'a': return _(this.AbrWDays[d.getDay()]); // Day of month with 2 digits - case 'd': return this.pad (d.getDate ()); + case 'd': return this.pad(d.getDate()); // Day of month - case 'e': return d.getDate (); + case 'e': return d.getDate(); // Complete month name - case 'B': return _(this.Months[d.getMonth ()]); + case 'B': return _(this.Months[d.getMonth()]); // Abreviated month name - case 'b': return _(this.AbrMonths[d.getMonth ()]); + case 'b': return _(this.AbrMonths[d.getMonth()]); // Month number with 2 digits - case 'm': return this.pad (d.getMonth () + 1); + case 'm': return this.pad(d.getMonth() + 1); // Year with 4 digits - case 'Y': return d.getFullYear (); + case 'Y': return d.getFullYear(); // Complete date without year - case 'D': return _(this.tokenD).replace (this.regexp, this.regexpFunc.bind (this, d)); + case 'D': return _(this.tokenD).replace(this.regexp, this.regexpFunc.bind(this, d)); } return token; } - ,strftime: function (date, format) - { + ,strftime: function(date, format) { if (!date) return ''; + if (!(date instanceof Date)) + date = new Date(date); - return format.replace (this.regexp, this.regexpFunc.bind (this, date)); + return format.replace(this.regexp, this.regexpFunc.bind(this, date)); } }; - diff --git a/package.json b/package.json index 91e00da1..74398542 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hedera-web", - "version": "1.407.12", + "version": "1.407.13", "description": "Verdnatura web page", "license": "GPL-3.0", "repository": { diff --git a/rest/core/query.php b/rest/core/query.php index 998e1d5a..a188e300 100644 --- a/rest/core/query.php +++ b/rest/core/query.php @@ -163,10 +163,10 @@ class Query extends Vn\Web\JsonRequest { * Transforms the database value into a JSON parseable value. **/ function castValue($value, $type) { - if ($value == '' && $type != Type::STRING) + if ($value === '' && $type != Type::STRING) $value = NULL; - if (!empty($value)) + if ($value !== NULL) switch ($type) { case Type::BOOLEAN: return (bool) $value;