+ ns._date_format = {
+ sep: '.',
+ y: 2,
+ m: 1,
+ d: 0
+ };
+ ns._time_format = {
+ sep: ':',
+ h: 0,
+ m: 1,
+ };
+ ns._number_format = {
+ decimalSep: ',',
+ thousandSep: '.'
+ };
+
+ ns.setup_formats = function(params) {
+ var res = (params.dates || "").match(/^([ymd]+)([^a-z])([ymd]+)[^a-z]([ymd]+)$/);
+ if (res) {
+ ns._date_format = { sep: res[2] };
+ ns._date_format[res[1].substr(0, 1)] = 0;
+ ns._date_format[res[3].substr(0, 1)] = 1;
+ ns._date_format[res[4].substr(0, 1)] = 2;
+ }
+
+ res = (params.times || "").match(/^([hm]+)([^a-z])([hm]+)$/);
+ if (res) {
+ ns._time_format = { sep: res[2] };
+ ns._time_format[res[1].substr(0, 1)] = 0;
+ ns._time_format[res[3].substr(0, 1)] = 1;
+ }
+
+ res = (params.numbers || "").match(/^\d*([^\d]?)\d+([^\d])\d+$/);
+ if (res)
+ ns._number_format = {
+ decimalSep: res[2],
+ thousandSep: res[1]
+ };
+ };
+
+ ns.parse_date = function(date) {
+ if (date === undefined)
+ return undefined;
+
+ if (date === '')
+ return null;
+
+ if (date === '0' || date === '00')
+ return new Date();
+
+ var parts = date.replace(/\s+/g, "").split(ns._date_format.sep);
+ var today = new Date();
+
+ // without separator?
+ // assume fixed pattern, and extract parts again
+ if (parts.length == 1) {
+ date = parts[0];
+ parts = date.match(/../g);
+ if (date.length == 8) {
+ parts[ns._date_format.y] += parts.splice(ns._date_format.y + 1, 1)
+ }
+ else
+ if (date.length == 6 || date.length == 4) {
+ }
+ else
+ if (date.length == 1 || date.length == 2) {
+ parts = []
+ parts[ ns._date_format.y ] = today.getFullYear();
+ parts[ ns._date_format.m ] = today.getMonth() + 1;
+ parts[ ns._date_format.d ] = date;
+ }
+ else {
+ return undefined;
+ }
+ }
+
+ if (parts.length == 3) {
+ var year = +parts[ ns._date_format.y ] || 0 * 1 || (new Date()).getFullYear();
+ if (year > 9999)
+ return undefined;
+ if (year < 100) {
+ year += year > 70 ? 1900 : 2000;
+ }
+ date = new Date(
+ year,
+ (parts[ ns._date_format.m ] || (today.getMonth() + 1)) * 1 - 1, // Months are 0-based.
+ (parts[ ns._date_format.d ] || today.getDate()) * 1
+ );
+ } else if (parts.length == 2) {
+ date = new Date(
+ (new Date()).getFullYear(),
+ (parts[ (ns._date_format.m > ns._date_format.d) * 1 ] || (today.getMonth() + 1)) * 1 - 1, // Months are 0-based.
+ (parts[ (ns._date_format.d > ns._date_format.m) * 1 ] || today.getDate()) * 1
+ );
+ } else
+ return undefined;
+
+ return isNaN(date.getTime()) ? undefined : date;
+ };
+
+ ns.format_date = function(date) {
+ if (isNaN(date.getTime()))
+ return undefined;
+
+ var parts = [ "", "", "" ]
+ parts[ ns._date_format.y ] = date.getFullYear();
+ parts[ ns._date_format.m ] = (date.getMonth() < 9 ? "0" : "") + (date.getMonth() + 1); // Months are 0-based, but days are 1-based.
+ parts[ ns._date_format.d ] = (date.getDate() < 10 ? "0" : "") + date.getDate();
+ return parts.join(ns._date_format.sep);
+ };
+
+ ns.parse_time = function(time) {
+ var now = new Date();
+
+ if (time === undefined)
+ return undefined;
+
+ if (time === '')
+ return null;
+
+ if (time === '0')
+ return now;
+
+ // special case 1: military time in fixed "hhmm" format
+ if (time.length == 4) {
+ var res = time.match(/(\d\d)(\d\d)/);
+ if (res) {
+ now.setHours(res[1], res[2]);
+ return now;
+ } else {
+ return undefined;
+ }
+ }
+
+ var parts = time.replace(/\s+/g, "").split(ns._time_format.sep);
+ if (parts.length == 2) {
+ for (var idx in parts) {
+ if (Number.isNaN(Number.parseInt(parts[idx])))
+ return undefined;
+ }
+ now.setHours(parts[ns._time_format.h], parts[ns._time_format.m]);
+ return now;
+ } else
+ return undefined;
+ }
+
+ ns.format_time = function(date) {
+ if (isNaN(date.getTime()))
+ return undefined;
+
+ var parts = [ "", "" ]
+ parts[ ns._time_format.h ] = date.getHours().toString().padStart(2, '0');
+ parts[ ns._time_format.m ] = date.getMinutes().toString().padStart(2, '0');
+ return parts.join(ns._time_format.sep);
+ };
+
+ ns.parse_amount = function(amount) {
+ if (amount === undefined)
+ return undefined;
+
+ if (amount === '')
+ return null;
+
+ if (ns._number_format.decimalSep == ',')
+ amount = amount.replace(/\./g, "").replace(/,/g, ".");
+
+ amount = amount.replace(/[\',]/g, "");
+
+ // Make sure no code wich is not a math expression ends up in eval().
+ if (!amount.match(/^[0-9 ()\-+*/.]*$/))
+ return undefined;
+
+ amount = amount.replace(/^0+(\d+)/, '$1');
+
+ /* jshint -W061 */
+ try {
+ return eval(amount);
+ } catch (err) {
+ return undefined;
+ }
+ };
+
+ ns.round_amount = function(amount, places) {
+ var neg = amount >= 0 ? 1 : -1;
+ var mult = Math.pow(10, places + 1);
+ var temp = Math.abs(amount) * mult;
+ var diff = Math.abs(1 - temp + Math.floor(temp));
+ temp = Math.floor(temp) + (diff <= 0.00001 ? 1 : 0);
+ var dec = temp % 10;
+ temp += dec >= 5 ? 10 - dec: dec * -1;
+
+ return neg * temp / mult;
+ };
+
+ ns.format_amount = function(amount, places) {
+ amount = amount || 0;
+
+ if ((places !== undefined) && (places >= 0))
+ amount = ns.round_amount(amount, Math.abs(places));
+
+ var parts = ("" + Math.abs(amount)).split(/\./);
+ var intg = parts[0];
+ var dec = parts.length > 1 ? parts[1] : "";
+ var sign = amount < 0 ? "-" : "";
+
+ if (places !== undefined) {
+ while (dec.length < Math.abs(places))
+ dec += "0";
+
+ if ((places > 0) && (dec.length > Math.abs(places)))
+ dec = d.substr(0, places);
+ }
+
+ if ((ns._number_format.thousandSep !== "") && (intg.length > 3)) {
+ var len = ((intg.length + 2) % 3) + 1,
+ start = len,
+ res = intg.substr(0, len);
+ while (start < intg.length) {
+ res += ns._number_format.thousandSep + intg.substr(start, 3);
+ start += 3;
+ }
+
+ intg = res;
+ }
+
+ var sep = (places !== 0) && (dec !== "") ? ns._number_format.decimalSep : "";
+
+ return sign + intg + sep + dec;
+ };