APNS - Node APN - payload - single quote - json

I am testing push notification using the node-apn module in node js. All works fine except that special characters such as a single quote does not properly escape. The push notification with a single quote (i.e. we'll becomes we\'ll in the actual notification). I tried regex, mongoose.toObject, message.message.toString() to no avail.
Message.findOne(query).lean().exec(function (err, doc){
if (!doc || doc == null) {
message.save(function(e) {
console.log("message saved")
if (e) {
console.log("there is an error")
console.log(e)
} else {
console.log(message.device_token)
var mesg = message.toObject();
var msg = JSON.stringify(mesg);
var payload = {
"contact" : message.contact,
"did" : message.did,
"id" : message.message_id,
"date" : message.date,
"message" : message.message
}
var clean = message.message.toString().replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
var note = new apns.Notification();
var myDevice = new apns.Device(message.device_token);
note.expiry = Math.floor(Date.now() / 1000) + 3600; // Expires 1 hour from now.
note.badge = 3;
note.alert = message.message;
note.payload = payload;
apnsConnection.pushNotification(note, myDevice);
}
})
}
});
});

I solved this issue by escaping the json formmatted single quote (which was //') in the message.message value using the replace function:
var messageStringCleaned = message.message.toString().replace(/\\/g,"");
var payload = {
"contact" : message.contact,
"did" : message.did,
"id" : message.message_id,
"date" : message.date,
"message" : messageStringCleaned
}
var note = new apns.Notification();
var myDevice = new apns.Device(message.device_token);
note.expiry = Math.floor(Date.now() / 1000) + 3600; // Expires 1 hour from now.
note.badge = 3;
note.alert = messageStringCleaned;
note.payload = payload;
apnsConnection.pushNotification(note, myDevice);

Related

Alexa (Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '[', got 'undefined')

My code is not working when I test it in Amazon Developer and I don't see anything wrong with my code. It says my response is invalid.
Here's the code I tried to run but failed(I ran one response but not the other):
var Alexa = require('alexa-sdk');
exports.handler = function(event, context, callback) {
var alexa = Alexa.handler(event, context);
// alexa.dynamoDBTableName = 'YourTableName'; // creates new table for userid:session.attributes
alexa.registerHandlers(handlers);
alexa.execute();
};
var handlers = {
'LaunchRequest': function () {
this.emit('WelcomeIntent');
},
'WelcomeIntent': function () {
this.emit(':ask', 'Welcome to the guessing game! What difficulty would you like to play? Easy, Medium, or Hard?');
},
//------------------------------------------------------------------------------------------------------------------------------------------------
'DifficultyIntent': function (){
var difficulty = this.event.request.intent.slots.difficulty.value;
var range = 10; this.attributes['RandomNumberEnd'] = range;
if (difficulty === 'easy')
{ range = 10;
this.emit[':ask Your range is 1 - ' + range]
}
else if (difficulty === 'medium')
{ range = 100;
this.emit[':ask Your range is 1 - ' + range]
}
else (difficulty === 'hard');
{ range = 1000;
this.emit[':ask Your range is 1 - ' + range]
}
var randomNumber = Math.floor((Math.random()*range)+1);
var rightAnswer = this.attributes['rightAnswer'] = rightAnswer;
}, //check the user's guess with the right answer
'UserGuessIntent': function (){
var guess = this.event.request.intent.slots.guess.value;
this.attributes['guess'] = guess;
this.emit('CheckIntent'); },
'CheckIntent': function (){
var guess = this.attributes['guess'];
this.attributes['rightAnswer'] = randomNumber;
if(guess < rightAnswer){
this.emit(':ask', 'Try Again! Guess higher!');
}
else if(guess > rightAnswer)
{this.emit(':ask', 'Try Again! Guess lower!');
}
else{
this.emit(':tell', 'You are correct! Congratulations!');
}
},
'QuitIntent': function(){
var stop = this.event.request.intent.slots.stop.value;
this.emit('AMAZON.StopIntent');
},
'AMAZON.StopIntent' : function(){
var rightAnswer = this.attributes['rightAnswer'];
this.emit(':tell', 'The right answer is ' + rightAnswer + '. Goodbye!');
}
};

Mongoose save isn't inserting anything

var mongoose = require('mongoose');
var url = mongoUrl + dbCollectionName; //external var
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
console.log(getTimeStamp() + 'Connected to Mongo with Mongoose');
insertDocuments(db, function () {
});
});
mongoose.connect(url);
// Creating our Schema
var ackSchema = mongoose.Schema({
hostgroup : String,
host : String,
service : String,
timePeriod : String,
startTime : Number,
ackTime : Number,
deltaTime : Number,
caseNumb : String,
state : Number,
author : String,
ackId : Number,
});
// Creation our model
var ackModel = mongoose.model(collectionName, ackSchema);
//////////////////////////////////////
//// Functions
var insertDocuments = function(db, callback) {
// Get the documents collection
var collection = db.collection(collectionName);
var returnValue = 0,
caseValue = "";
// Find item to compare
collection.find({}).toArray( function (err, docs) {
// If Collection does not exist => 0, else 1
if (docs.length === 0) {
colExist = 0;
console.log(getTimeStamp() + 'Collection is empty. If needed application will create "' + collectionName + '" collection while inserting items.');
} else {
colExist = 1;
console.log(getTimeStamp() + 'Collection "' + collectionName + '" exist, item will be added');
};
// SQL Query to fetch row
mysqlQuery(function (row) {
//// IF 8/20
if (row.timeperiod == timePeriod820) {
returnValue = timePeriodCalc(row); // Function from timeperiod.js
deltaValue = parseInt(returnValue.slice(6)); // Get our Delta Value
caseValue = returnValue.slice(0,4); // Get the Case Number, verification purpose
//// ELSE 24/7
} else {
deltaValue = (row.ack_time - row.start_time);
caseValue = 'C.0';
};
var ack = new ackModel({
hostgroup : row.hostgroup,
host : row.hostname,
service : row.servicename,
timePeriod : row.timeperiod,
startTime : row.start_time,
ackTime : row.ack_time,
state : row.state,
deltaTime : deltaValue,
caseNumb : caseValue,
author : row.author,
ackId : row.ack_id
});
console.log(ack);
ack.save(function (err, ack) {
if (err) {
console.log(getTimeStamp() + 'Mongoose .save error : ' + err);
}
else {
console.log(getTimeStamp() + 'SAVE Mongoose : ' + ack.author + ' ' + ack.ackId);
}
});
});
callback(docs);
});
};
As you can see i'm fetching some raws from a MySQL databse to put them into a mongo database. The problem is that ack.save() doesn't save anything when the ack var is perfectly ready to be saved.
This is how ack is filled (from console.log(ack) ) :
{ _id: 568d360867e31d11001206f7,
ackId: 1087,
author: 'pilote1',
caseNumb: 'C.10',
deltaTime: -3481,
state: 2,
ackTime: 1452091450,
startTime: 1452094931,
timePeriod: 'RESSOURCES-GPE-N1-8/20',
service: 'Service-Random-1M',
host: 'PRO_HOST3',
hostgroup: 'PROSERVIA' }

Parse URL (ActionScript 3.0)

I would like to know how would one parse an URL.
protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes
I need to get "this_is_what_i_want/even_if_it_has_slashes"
How should I do this?
Thanks!
Try this :
var u:String = 'protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes',
a:Array = u.split('/'),
s:String = ''
for(var i=0; i<a.length; i++){
if(i > 3){
s += '/'+a[i]
}
}
trace(s) // gives : /morethings/this_is_what_i_want/even_if_it_has_slashes
Another approach would be using Regex like this:
.*?mydomain\.com[^\/]*\/[^\/]+\/[^\/]+\/([^?]*)
(Breakdown of the components.)
This looks for a pattern where it skips whatever comes before the domain name (doesn't matter if the protocol is specified or not), skips the domain name + TLD, skips any port number, and skips the first two sub path elements. It then selects whatever comes after it but skips any query strings.
Example: http://regexr.com/39r69
In your code, you could use it like this:
var url:String = "protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes";
var urlExp:RegExp = /.*?mydomain\.com[^\/]*\/[^\/]+\/[^\/]+\/([^?]*)/g;
var urlPart:Array = urlExp.exec(url);
if (urlPart.length > 1) {
trace(urlPart[1]);
// Prints "this_is_what_i_want/even_if_it_has_slashes"
} else {
// No matching part of the url found
}
As you can see on the regexr link above, this captures the part "this_is_what_i_want/even_if_it_has_slashes" for all of these variations of the url:
protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes
protocol://mydomain.com:8080/something/morethings/this_is_what_i_want/even_if_it_has_slashes
protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes.html
protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes.html?hello=world
mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes
protocol://subdomain.mydomain.com:8080/something/morethings/this_is_what_i_want/even_if_it_has_slashes
Edit: Fixed typo in regexp string
Simple way,
var file:String = 'protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes';
var splitted:Array = file.split('/');
var str1:String = splitted.splice(3).join('/'); //returns 'something/morethings/this_is_what_i_want/even_if_it_has_slashes'
var str1:String = splitted.splice(5).join('/'); //returns 'this_is_what_i_want/even_if_it_has_slashes'
If you want to be a little more flexible in the feature (e.g. you need the domain), you can use my Url class.
Class for URL parsing
package
{
import flash.net.URLVariables;
public class Url
{
protected var protocol:String = "";
protected var domain:String = "";
protected var port:int = 0;
protected var path:String = "";
protected var parameters:URLVariables;
protected var bookmark:String = "";
public function Url(url:String)
{
this.init(url);
}
protected function splitSingle(value:String, c:String):Object
{
var temp:Object = {first: value, second: ""};
var pos:int = value.indexOf(c);
if (pos > 0)
{
temp.first = value.substring(0, pos);
temp.second = value.substring(pos + 1);
}
return temp;
}
protected function rtrim(value:String, c:String):String
{
while (value.substr(-1, 1) == c)
{
value = value.substr(0, -1);
}
return value;
}
protected function init(url:String):void
{
var o:Object;
var urlExp:RegExp = /([a-z]+):\/\/(.+)/
var urlPart:Array = urlExp.exec(url);
var temp:Array;
var rest:String;
if (urlPart.length <= 1)
{
throw new Error("invalid url");
}
this.protocol = urlPart[1];
rest = urlPart[2];
o = this.splitSingle(rest, "#");
this.bookmark = o.second;
rest = o.first;
o = this.splitSingle(rest, "?");
o.second = this.rtrim(o.second, "&");
this.parameters = new URLVariables();
if (o.second != "")
{
try
{
this.parameters.decode(o.second);
}
catch (e:Error)
{
trace("Warning: cannot decode URL parameters. " + e.message + " " + o.second);
}
}
rest = o.first
o = this.splitSingle(rest, "/");
if (o.second != "")
{
this.path = "/" + o.second;
}
rest = o.first;
o = this.splitSingle(rest, ":");
if (o.second != "")
{
this.port = parseInt(o.second);
}
else
{
switch (this.protocol)
{
case "https":
this.port = 443;
break;
case "http":
this.port = 80;
break;
case "ssh":
this.port = 22;
break;
case "ftp":
this.port = 21;
break;
default:
this.port = 0;
}
}
this.domain = o.first;
}
public function getDomain():String
{
return this.domain;
}
public function getProtocol():String
{
return this.protocol;
}
public function getPath():String
{
return this.path;
}
public function getPort():int
{
return this.port;
}
public function getBookmark():String
{
return this.bookmark;
}
public function getParameters():URLVariables
{
return this.parameters;
}
}
}
Example usage
try {
var myUrl:Url = new Url("protocol://mydomain.com/something/morethings/this_is_what_i_want/even_if_it_has_slashes");
trace("Protocol: " + myUrl.getProtocol());
trace("Domain: " + myUrl.getDomain());
trace("Path: " + myUrl.getPath());
trace("What you want: " + myUrl.getPath().split("/").splice(2).join("/") );
} catch (e:Error) {
trace("Warning: cannot parse url");
}
Output
Protocol: protocol
Domain: mydomain.com
Path: /something/morethings/this_is_what_i_want/even_if_it_has_slashes
What you want: morethings/this_is_what_i_want/even_if_it_has_slashes
Description
The init function checks with the regular expression if the given url starts with some letters (the protocol) followed by a colon, two slashes and more characters.
If the url contains a hash letter, everything behind its fist occurrence is taken as a bookmark
If the url contains a question mark, everything behind its fist occurrence is taken as key=value variables and parsed by the URLVariables class.
If the url contains a slash, everything behind its first occurrence is taken as the path
If the rest (everything between the last protocol slash and the first slash of the path) contains a colon, everything behind it will be converted to an integer and taken as the port. If the port is not set, a default will be set in dependency of the protocol
The rest is the domain
For answering your question, I use the path of the given url, split it by slash, cut of the 'something' and join it by slash.

Export multiple html tables to Excel

I've scavenged the inter web for answers and though I found some, they were mostly incomplete or not working.
What I'm trying to do is: I have a info page which displays information about a customer or server (or something else), this information is displayed in a table, sometimes multiple tables (I sometimes create my own table for some of the data and use Html.Grid(Model.list) to create tables for the rest of the data stored in lists, all on 1 page).
I found this website which is an awesome: http://www.excelmashup.com/ and does exactly what I want for 1 table, though I need this for multiple tables (they must all be in the same Excel file). I know I can create multiple files (1 for each table) but this is not the desired output.
So I kept on searching and I found a post on stackoverflow: Export multiple HTML tables to Excel with JavaScript function
This seemed promising so I tried using it but the code had some minor errors which I tried to fix:
var tableToExcel = (function () {
var uri = 'data:application/vnd.ms-excel;base64,'
, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>'
, base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }
return function (table, name) {
if (!table.nodeType) table = document.getElementById(table)
var ctx = { worksheet: name || 'Worksheet', table: table.innerHTML }
window.location.href = uri + base64(format(template, ctx))
}
})()
The button I use to trigger it:
<input type="button" onclick="tableToExcel('InformatieTable', 'W3C Example Table')" value="Export to Excel">
but alas to no avail (I did not know what to do with the if (!table.nodeType) table = table line so I just commented it since it seemed to do nothing special).
Now I get an error, or well not really an error but this is what it says when I try to run this code:
Resource interpreted as Document but transferred with MIME type application/vnd.ms-excel: "data:application/vnd.ms-excel;base64,PGh0bWwgeG1sbnM6bz0idXJuOnNjaGVtYXMtbW…JzZXQ9VVRGLTgiLz48L2hlYWQ+PGJvZHk+PHRhYmxlPjwvdGFibGU+PC9ib2R5PjwvaHRtbD4=".
And I get an Excel file as download in my browser but when I try to open it I get an error about the content and file extension not matching and if I would still like to open it. So if I click ok it opens a empty Excel sheet and that's it.
I am currently trying to fix that error, though i don't think it will make any difference to the content of the Excel file.
Is there anyone that can help me fix this? Or provide an other way of doing this?
I do prefer it to be run client side (so jQuery/java) instead of server side to minimize server load.
EDIT
I've found a better example of the jQuery (one that does work) on http://www.codeproject.com/Tips/755203/Export-HTML-table-to-Excel-With-CSS
This converts 1 table into an excel file which is obviously not good enough. But now I have the code to do this so I should be able to adapt it to loop trough all tables on the web page.
Also updated the code in this example to the correct version I'm using now.
I also still get the same error yet when I click on ok when trying to open the Excel file it does show me the content of the table, so I'm just ignoring that for now. anyone who has a solution for this please share.
Thanks to #Axel Richter I got my answer, he reffered me to the following question
I have adapted the code a bit so it would Take all the tables on the web page so it now looks like this:
<script type="text/javascript">
var tablesToExcel = (function () {
var uri = 'data:application/vnd.ms-excel;base64,'
, tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
+ '<Styles>'
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
+ '</Styles>'
+ '{worksheets}</Workbook>'
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{rows}</Table></Worksheet>'
, tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>'
, base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }
return function (wsnames, wbname, appname) {
var ctx = "";
var workbookXML = "";
var worksheetsXML = "";
var rowsXML = "";
var tables = $('table');
for (var i = 0; i < tables.length; i++) {
for (var j = 0; j < tables[i].rows.length; j++) {
rowsXML += '<Row>'
for (var k = 0; k < tables[i].rows[j].cells.length; k++) {
var dataType = tables[i].rows[j].cells[k].getAttribute("data-type");
var dataStyle = tables[i].rows[j].cells[k].getAttribute("data-style");
var dataValue = tables[i].rows[j].cells[k].getAttribute("data-value");
dataValue = (dataValue) ? dataValue : tables[i].rows[j].cells[k].innerHTML;
var dataFormula = tables[i].rows[j].cells[k].getAttribute("data-formula");
dataFormula = (dataFormula) ? dataFormula : (appname == 'Calc' && dataType == 'DateTime') ? dataValue : null;
ctx = {
attributeStyleID: (dataStyle == 'Currency' || dataStyle == 'Date') ? ' ss:StyleID="' + dataStyle + '"' : ''
, nameType: (dataType == 'Number' || dataType == 'DateTime' || dataType == 'Boolean' || dataType == 'Error') ? dataType : 'String'
, data: (dataFormula) ? '' : dataValue.replace('<br>', '')
, attributeFormula: (dataFormula) ? ' ss:Formula="' + dataFormula + '"' : ''
};
rowsXML += format(tmplCellXML, ctx);
}
rowsXML += '</Row>'
}
ctx = { rows: rowsXML, nameWS: wsnames[i] || 'Sheet' + i };
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
}
ctx = { created: (new Date()).getTime(), worksheets: worksheetsXML };
workbookXML = format(tmplWorkbookXML, ctx);
console.log(workbookXML);
var link = document.createElement("A");
link.href = uri + base64(workbookXML);
link.download = wbname || 'Workbook.xls';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
})();
</script>
so now when ever I want a page to have an option to be exported to excel i add a refference to that script and i add the following button to my page:
<button onclick="tablesToExcel(['ServerInformatie', 'Relaties'], 'VirtueleMachineInfo.xls', 'Excel')">Export to Excel</button>
so the method:
tablesToExcel(WorksheetNames, fileName, 'Excel')
Where worksheetNames is an array which needs to contain as much names (or more) as there are tables on the page. You could ofcourse chose to create the worksheet names in a different way.
And where fileName is ofcourse the name of the file you'll be downloading.
Not having it all in 1 worksheet is a shame but at least this will do for now.
Here is the code that I used to put multiple HTML tables in the same Excel sheet:
import TableExport from 'tableexport';
const tbOptions = {
formats: ["xlsx"], // (String[]), filetype(s) for the export, (default: ['xlsx', 'csv', 'txt'])
bootstrap: true, // (Boolean), style buttons using bootstrap, (default: true)
exportButtons: false, // (Boolean), automatically generate the built-in export buttons for each of the specified formats (default: true)
position: "bottom", // (top, bottom), position of the caption element relative to table, (default: 'bottom')
}
DowlandExcel = (key) => {
const table = TableExport(document.getElementById(key), tbOptions);
var exportData = table.getExportData();
var xlsxData = exportData[key].xlsx;
console.log(xlsxData); // Replace with the kind of file you want from the exportData
table.export2file(xlsxData.data, xlsxData.mimeType, xlsxData.filename, xlsxData.fileExtension, xlsxData.merges, xlsxData.RTL, xlsxData.sheetname)
}
DowlandExcelMultiTable = (keys) => {
const tables = []
const xlsxDatas = []
keys.forEach(key => {
const selector = document.getElementById(key);
if (selector) {
const table = TableExport(selector, tbOptions);
tables.push(table);
xlsxDatas.push(table.getExportData()[key].xlsx)
}
});
const mergeXlsxData = {
RTL: false,
data: [],
fileExtension: ".xlsx",
filename: 'rapor',
merges: [],
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
sheetname: "Rapor"
}
for (let i = 0; i < xlsxDatas.length; i++) {
const xlsxData = xlsxDatas[i];
mergeXlsxData.data.push(...xlsxData.data)
xlsxData.merges = xlsxData.merges.map(merge => {
const diff = mergeXlsxData.data.length - xlsxData.data.length;
merge.e.r += diff;
merge.s.r += diff;
return merge
});
mergeXlsxData.merges.push(...xlsxData.merges)
mergeXlsxData.data.push([null]);
}
console.log(mergeXlsxData);
tables[0].export2file(mergeXlsxData.data, mergeXlsxData.mimeType, mergeXlsxData.filename, mergeXlsxData.fileExtension, mergeXlsxData.merges, mergeXlsxData.RTL, mergeXlsxData.sheetname)
}

Funky IE JSON conversions

When running our AngularJS app in IE11 everything looks great in the debugger, but when our app encodes the data as JSON to save to our database, we get bad results.
Our app obtains a record from our database, then some manipulation is done and then the data is saved back to the server from another model.
Here is the data I got back from the server in the setAttendanceGetSInfo() function below:
{"data":{"Start":"2014-10-16T19:36:00Z","End":"2014-10-16T19:37:00Z"},
This is the code used to "convert the data" to 3 properties in our model:
var setAttendanceGetSInfo = function (CourseId, PID) {
return setAttendanceInfo(CourseId, PID)
.then(function (result) {
return $q.all([
$http.get("../api/Axtra/getSInfo/" + model.event.Id),
$http.get("../api/Axtra/GetStartAndEndDateTime/" + aRow.Rid)
]);
}).then(function (result) {
var r = result.data;
var e = Date.fromISO(r.Start);
var f = Date.fromISO(r.End);
angular.extend(model.event, {
examDate: new Date(e).toLocaleDateString(),
examStartTime: (new Date(e)).toLocaleTimeString(),
examEndTime: (new Date(f)).toLocaleTimeString()
});
return result.sInfo;
});
};
fromISO is defined as:
(function(){
var D= new Date('2011-06-02T09:34:29+02:00');
if(!D || +D!== 1307000069000){
Date.fromISO= function(s){
var day, tz,
rx=/^(\d{4}\-\d\d\-\d\d([tT ][\d:\.]*)?)([zZ]|([+\-])(\d\d):(\d\d))?$/,
p= rx.exec(s) || [];
if(p[1]){
day= p[1].split(/\D/);
for(var i= 0, L= day.length; i<L; i++){
day[i]= parseInt(day[i], 10) || 0;
};
day[1]-= 1;
day= new Date(Date.UTC.apply(Date, day));
if(!day.getDate()) return NaN;
if(p[5]){
tz= (parseInt(p[5], 10)*60);
if(p[6]) tz+= parseInt(p[6], 10);
if(p[4]== '+') tz*= -1;
if(tz) day.setUTCMinutes(day.getUTCMinutes()+ tz);
}
return day;
}
return NaN;
}
}
else{
Date.fromISO= function(s){
return new Date(s);
}
}
})()
Take a look at the screenshot of the event model data:
But, if I eval the event model using JSON.stringify(model.event), I get this:
{\"examDate\":\"?10?/?16?/?2014\",\"examStartTime\":\"?2?:?44?:?00? ?PM\",\"examEndTime\":\"?2?:?44?:?00? ?PM\"}
And this is the JSON encoded data that actually got stored on the DB:
"examDate":"¿10¿/¿16¿/¿2014","examStartTime":"¿2¿:¿36¿:¿00¿ ¿PM","examEndTime":"¿2¿:¿37¿:¿00¿ ¿PM"
What is wrong here and how can I fix this? It works exactly as designed in Chrome and Firefox. I have not yet tested on Safari or earlier versions of IE.
The toJSON for the date class isn't defined perfectly the same for all browsers.
(You can see a related question here: Discrepancy in JSON.stringify of date values in different browsers
I would suspect that you have a custom toJSON added to the Date prototype since your date string doesn't match the standard and that is likely where your issue is. Alternatively, you can use the Date toJSON recommended in the above post to solve your issues.
First, I modified the fromISO prototype to this:
(function () {
var D = new Date('2011-06-02T09:34:29+02:00');
if (!D || +D !== 1307000069000) {
Date.fromISO = function (s) {
var D, M = [], hm, min = 0, d2,
Rx = /([\d:]+)(\.\d+)?(Z|(([+\-])(\d\d):(\d\d))?)?$/;
D = s.substring(0, 10).split('-');
if (s.length > 11) {
M = s.substring(11).match(Rx) || [];
if (M[1]) D = D.concat(M[1].split(':'));
if (M[2]) D.push(Math.round(M[2] * 1000));// msec
}
for (var i = 0, L = D.length; i < L; i++) {
D[i] = parseInt(D[i], 10);
}
D[1] -= 1;
while (D.length < 6) D.push(0);
if (M[4]) {
min = parseInt(M[6]) * 60 + parseInt(M[7], 10);// timezone not UTC
if (M[5] == '+') min *= -1;
}
try {
d2 = Date.fromUTCArray(D);
if (min) d2.setUTCMinutes(d2.getUTCMinutes() + min);
}
catch (er) {
// bad input
}
return d2;
}
}
else {
Date.fromISO = function (s) {
return new Date(s);
}
}
Date.fromUTCArray = function (A) {
var D = new Date;
while (A.length < 7) A.push(0);
var T = A.splice(3, A.length);
D.setUTCFullYear.apply(D, A);
D.setUTCHours.apply(D, T);
return D;
}
Date.toJSON = function (key) {
return isFinite(this.valueOf()) ?
this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z' : null;
};
})()
Then I added moment.js and formatted the dates when they get stored:
var SaveAffRow = function () {
// make sure dates on coursedate and event are correct.
var cd = model.a.courseDate;
var ed = model.event.examDate;
var est = model.event.examStartTime;
var eet = model.event.examEndTime;
model.a.courseDate = moment(cd).format("MM/DD/YYYY");
model.event.examDate = moment(ed).format("MM/DD/YYYY");
model.event.examStartTime = moment(est).format("MM/DD/YYYY hh:mm A");
model.event.examEndTime = moment(eet).format("MM/DD/YYYY hh:mm A");
affRow.DocumentsJson = angular.toJson({a: model.a, event: model.event});
var aff = {};
if (affRow.Id != 0)
aff = affRow.$update({ Id: affRow.Id });
else
aff = affRow.$save({ Id: affRow.Id });
return aff;
};
and when they get read (just in case they are messed up already):
var setAttendanceGetSInfo = function (CourseId, PID) {
return setAttendanceInfo(CourseId, PID)
.then(function (result) {
return $q.all([
$http.get("../api/Axtra/getSInfo/" + model.event.Id),
$http.get("../api/Axtra/GetStartAndEndDateTime/" + aRow.Rid)
]);
}).then(function (result) {
var r = result.data;
var e = Date.fromISO(r.Start);
var f = Date.fromISO(r.End);
angular.extend(model.event, {
examDate: moment(e).format("MM/DD/YYYY"),
examStartTime: moment(e).format("MM/DD/YYYY hh:mm A"),
examEndTime: moment(f).format("MM/DD/YYYY hh:mm A")
});
return result.sInfo;
});
};