JavaScript function to re-arrange date format - javascript

I'm working on some analytics, using Google Tag Manager.
We have a datalayer on the site, one of the value's is a date in format DDMMYYYY.
For a media tag I need to change this date to YYYY-MM-DD.
I'm trying something like this as an example: but I can't get it to work.
I am a total novice with Javascript
(function(){
var d = {{Departure_Date}}
var u = {{Departure_Date}}.replace(/(\d{2})(\d{2})(\d{4})/,'$3$2$1')
return u
})()
Here {{Departure_Date}} is a variable that access the dataLayer and pulls out the original date format.
Any help would be greatly appreciated.

[assuming {{Departure_Date}} is a string, like '04032003']
Almost there. Try [ddmmyyyy].replace(/^(\d{2})(\d{2})(\d{4})$/, '$3-$2-$1'). Alternatively, you can slice up the ddmmyyyy string (see snippet)
var res = document.querySelector('#result');
res.innerHTML = 'input: 20052014, output: ' +
'20052015'.replace(/^(\d{2})(\d{2})(\d{4})$/, '$3-$2-$1');
// Alternative:
var inp = '18072013';
res.innerHTML += '<br>input: 18072013, output: ' +
[inp.slice(4), inp.slice(2,4), inp.slice(0,2)].join('-');
<div id="result"><div>

Related

internet explorer match() not working correctly

I have a really weird error on IE.
I am using knockout custom validations. And one of my custom validations is to validate date.
function:
function isValidDate(txtDate) {
var currVal = txtDate;
if (currVal == '' || currVal == null)
return false;
//Declare Regex
var rxDatePattern = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
var dtArray = currVal.match(rxDatePattern); // is format OK?
if (dtArray == null)
return false;
/*continue of logic*/
}
This works great, when I run it first time. But then I do a redirect to server and return to the same page.
And the validation is called again at that point the problem begins.
I have a two snapshots of memory. They look identical to me. But there has to be some difference that I don't see or the match method is somehow broken.
The difference is not the dtArray == null that is the problem. You can try to run it in console. And it parse the dtArray correctly....
Both snapshot are on the same line ( if (dtArray == null) )
beforeRedirect:
afterRedirect:
Update. I solved my problem.
problem was that I was setting my observable property something like this:
var date = "1990-01-01T00:00:00";
var dob = new Date(date).toLocaleDateString();
masterModel.Dob(dob);
when I do it like this the match works fine now:
var date = "1990-01-01T00:00:00"
var dob = new Date(date);
var dobstring = dob.getDate() + "/" + (dob.getMonth()+1) + "/" + dob.getFullYear();
masterModel.Dob(dobstring);
if you want to see the difference run this on IE in console. My IE version is 11.0.9600
//because I am in UK my locale string is dd/MM/yyyy if you get different one this problem won't work for you!
var date = "1990-01-01T00:00:00"
var dob = new Date(date).toLocaleDateString();
var rxDatePattern = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
console.log(dob);
console.log(dob.match(rxDatePattern));
//vs
var date = "1990-01-01T00:00:00"
var dob = new Date(date);
var dobstring = dob.getDate() + "/" + (dob.getMonth()+1) + "/" + dob.getFullYear();
var rxDatePattern = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
console.log(dobstring);
console.log(dobstring.match(rxDatePattern));
Try simply checking for falsy values. The empty string, null and undefined are all falsy, there is no need to be more specific than that here.
function isValidDate(txtDate) {
if (!txtDate) return false;
var rxDatePattern = /^(\d{1,2})(\/|-)(\d{1,2})(\/|-)(\d{4})$/;
var dtArray = currVal.match(rxDatePattern);
if (!dtArray) return false;
/*continue of logic*/
}
That being said, I strongly suggest you use a date library (most prominently: moment.js) to do any date parsing, -calculation and -validation work. Don't roll your own regex when a fully functional and properly tested library has been written.
To think one step further, with knockout it's much easier to store an actual date object in an observable, so there is no need to parse any date strings at all, ever. You can also format it for display on screen any way you like, instead of limiting yourself/the user to a single format.
This way you would not need to do any date format validation at all. Either the observable contains a date - or not. For best effect use that together with a date picker widget (for example the one from knockout-jqueryui).
View model:
this.exampleDate = ko.observable();
View, assuming jQueryUI + knockout-jqueryui:
<input type="text" data-bind="datepicker: {
dateFormat: 'dd.mm.yyyy'
}, value: exampleDate" />

A string of form nnnn-nnnn is displayed in a spreadsheet as a date or otherwise incorrectly

I have a script I have been using in my test environment to programmically create a tracking number by parsing the year from timestamp and padding the response index.
function setTrackingNumber(ss, lastRowInx, createDateColumn) //This block generates and stores a tracking number in Column AU on the backend
{
var padTrackNo = "" + lastRowInx;
var trackSize = 4;
var trackingNumberColumn = createDateColumn-3; //trackingNumberColumn is currently in AU (Column 47) Calculating using it's relative position to createDateColumn Position
if (ss.getRange(lastRowInx, trackingNumberColumn).getValue() == "") // so that subsequent edits to Google Form don't overwrite original tracking number
{
if (padTrackNo > trackSize)
{
var padTrackNo = pad(padTrackNo, trackSize);
}
else {} //do nothing
var shortYear = setShortYear(ss, lastRowInx, createDateColumn);
var trackingNumber = shortYear + "-" + padTrackNo;
var createTrackingNumber = ss.getRange(lastRowInx, trackingNumberColumn);
createTrackingNumber.setValue(trackingNumber);
}
else {} //should do nothing
return;
}//This is the end of the setTrackingNumber function
function setShortYear(ss, lastRowInx, createDateColumn)
{
var newCreateDate = ss.getRange(lastRowInx,createDateColumn).getValue();
var strDate = "" + newCreateDate;
var splitDate = strDate.split(" ");
var trimYear = splitDate[3];
var shortYear = trimYear;
return shortYear;
}//This is the end of the shortYear function
function pad(padTrackNo, trackSize)
{
while (padTrackNo.length < trackSize)
{
padTrackNo = "0"+padTrackNo;
}
return padTrackNo;
}//This is the end of pad function
That gets me test result which is as expected ex. 2016-0005. However when we added it to another production sheet it seemed to work with test data and then production data showed up like a date 3/1/2016. production result - first cell.
I thought it must just be formatting the string as a date because of the numbers so I tried formatted the column as plain text but that just changed the date to a plain text version of the date.
I thought this might be similar to needing to specify the format like I did in this question Appending initial timestamp from Google Form to end of record in order to permanently store create date onFormSubmit at #SandyGood 's suggestion so I tried setting the number format as [0000-0000] by changing
createTrackingNumber.setValue(trackingNumber);
to
createTrackingNumber.setValue(trackingNumber).setNumberFormat("0000-0000");
which resulted in the [production result - second cell] which again doesn't match the expected result.
Oddly, some submissions seem to work just fine like [production result - third cell]. Over the past 3 days and approximately 10 records it has been fine, then hinky, then fine, they hinky, then fine again. I am not really sure what else to try to debug this odd behaviour.
Note: I had to parse the date as a string as I was having trouble getting it to parse the date correctly from the create date which is taken from initial timestamp.
To my understanding, "2016-0005" is not a number but a string, so the cell containing it should be formatted as plain text. With a script, this can be done by
range.setNumberFormat('#STRING#')
(source), and this must be done before you set the value to the cell. Like this:
createTrackingNumber.setNumberFormat('#STRING#').setValue(trackingNumber);

Replace array-mapped variables with the actual variable name/string?

I am trying to edit a Greasemonkey/jQuery script. I can't post the link here.
The code is obfuscated and compressed with minify.
It starts like this:
var _0x21e9 = ["\x67\x65\x74\x4D\x6F\x6E\x74\x68", "\x67\x65\x74\x55\x54\x43\x44\x61\x74\x65", ...
After "decoding" it, I got this:
var _0x21e9=["getMonth","getUTCDate","getFullYear", ...
It is a huge list (500+ ). Then, it has some variables like this:
month = date[_0x21e9[0]](), day = date[_0x21e9[1]](), ...
_0x21e9[0] is getMonth, _0x21e9[1] is getUTCDate, etc.
Is it possible to replace the square brackets with the actual variable name? How?
I have little knowledge in javascript/jQuery and can not "read" the code the way it is right now.
I just want to use some functions from this huge script and remove the others I do not need.
Update: I tried using jsbeautifier.org as suggested here and in the duplicated question but nothing changed, except the "indent".
It did not replace the array variables with the decoded names.
For example:
jsbeautifier still gives: month = date[_0x21e9[0]]().
But I need: month = date["getMonth"]().
None of the online deobfuscators seem to do this, How can I?
Is there a way for me to share the code with someone, at least part of it? I read I can not post pastebin, or similar here. I can not post it the full code here.
Here is another part of the code:
$(_0x21e9[8] + vid)[_0x21e9[18]]();
[8] is "." and [18] is "remove". Manually replacing it gives a strange result.
I haven't seen any online deobfuscator that does this yet, but the principle is simple.
Construct a text filter that parses the "key" array and then replaces each instance that that array is referenced, with the appropriate array value.
For example, suppose you have a file, evil.js that looks like this (AFTER you have run it though jsbeautifier.org with the Detect packers and obfuscators? and the Unescape printable chars... options set):
var _0xf17f = ["(", ")", 'div', "createElement", "id", "log", "console"];
var _0x41dcx3 = eval(_0xf17f[0] + '{id: 3}' + _0xf17f[1]);
var _0x41dcx4 = document[_0xf17f[3]](_0xf17f[2]);
var _0x41dcx5 = _0x41dcx3[_0xf17f[4]];
window[_0xf17f[6]][_0xf17f[5]](_0x41dcx5);
In that case, the "key" variable would be _0xf17f and the "key" array would be ["(", ")", ...].
The filter process would look like this:
Extract the key name using text processing on the js file. Result: _0xf17f
Extract the string src of the key array. Result:
keyArrayStr = '["(", ")", \'div\', "createElement", "id", "log", "console"]';
In javascript, we can then use .replace() to parse the rest of the JS src. Like so:
var keyArrayStr = '["(", ")", \'div\', "createElement", "id", "log", "console"]';
var restOfSrc = "var _0x41dcx3 = eval(_0xf17f[0] + '{id: 3}' + _0xf17f[1]);\n"
+ "var _0x41dcx4 = document[_0xf17f[3]](_0xf17f[2]);\n"
+ "var _0x41dcx5 = _0x41dcx3[_0xf17f[4]];\n"
+ "window[_0xf17f[6]][_0xf17f[5]](_0x41dcx5);\n"
;
var keyArray = eval (keyArrayStr);
//-- Note that `_0xf17f` is the key name we already determined.
var keyRegExp = /_0xf17f\s*\[\s*(\d+)\s*\]/g;
var deObsTxt = restOfSrc.replace (keyRegExp, function (matchStr, p1Str) {
return '"' + keyArray[ parseInt(p1Str, 10) ] + '"';
} );
console.log (deObsTxt);
if you run that code, you get:
var _0x41dcx3 = eval("(" + '{id: 3}' + ")");
var _0x41dcx4 = document["createElement"]("div");
var _0x41dcx5 = _0x41dcx3["id"];
window["console"]["log"](_0x41dcx5);
-- which is a bit easier to read/understand.
I've also created an online page that takes JS source and does all 3 remapping steps in a slightly more automated and robust manner. You can see it at:
jsbin.com/hazevo
(Note that that tool expects the source to start with the "key" variable declaration, like your code samples do)
#Brock Adams solution is brilliant, but there is a small bug: it doesn't take into account simple quoted vars.
Example:
var _0xbd34 = ["hello ", '"my" world'];
(function($) {
alert(_0xbd34[0] + _0xbd34[1])
});
If you try to decipher this example, it will result on this:
alert("hello " + ""my" world")
To resolve this, just edit the replacedSrc.replace into #Brock code:
replacedSrc = replacedSrc.replace (nameRegex, function (matchStr, p1Str) {
var quote = keyArry[parseInt (p1Str, 10)].indexOf('"')==-1? '"' : "'";
return quote + keyArry[ parseInt (p1Str, 10) ] + quote;
} );
Here you have a patched version.
for (var i = 0; i < _0x21e9.length; i++) {
var funcName = _0x21e9[i];
_0x21e9[funcName] = funcName;
}
this will add all the function names as keys to the array. allowing you to do
date[_0x21e9["getMonth"]]()

Google Apps Script - Dynamically Add Remove UiApp Form Elements

I am looking to create a Ui form section in my application that will Dynamically Add Remove UiApp Form Elements. I was trying to use the example from App Script Tutorials here
This example works great as far as performing the add remove elements, but when I use the submit button to capture the values, it submits as a JSON.stringify format. When I just want to capture the values only in a text or string format that will be added to a html email.
If there is way to convert JSON.stringify to text, string or get the values only in format, I will continue to use this example.
If not I was wonder if the following Javascript HTML code can be convert into GAS code and able to capture the values for each entry in a HTML email template to using in MailApp.
http://jsfiddle.net/g59K7/
Any suggestions, examples or adjustments to the codes would be greatly appreciated.
Thank you in advance
If you don't want the result to be in a JSON object, then you can adjust the _processSubmittedData(e) function. Right now he has it writing everything to an Object, which is fine. All you have to do is have a way to parse it:
function _processSubmittedData(e){
var result = {};
result.groupName = e.parameter.groupName;
var numMembers = parseInt(e.parameter.table_tag);
result.members = [];
//Member info array
for(var i=1; i<=numMembers; i++){
var member = {};
member.firstName = e.parameter['fName'+i];
member.lastName = e.parameter['lName'+i];
member.dateOfBirth = e.parameter['dob'+i];
member.note = e.parameter['note'+i];
result.members.push(member);
}
var htmlBody = 'Group Name: ' + result.groupName;
for(var a in result.members) {
var member = result.members[a];
var date = member.dateOfBirth;
var last = member.lastName;
var first = member.firstName;
var note = member.note;
htmlBody += first + ' ' + last + ' was born on ' + date + ' and has this note: ' + note;
}
MailApp.sendEmail('fakeEmail#fake.com',"Test Subject Line", "", {htmlBody: htmlBody});
}

Adding User input without rounding (Google Apps Script)

I am adding a users input in to UI as they add numbers and returning the results. The input is currency so I need to carry it out two decimals and not round.
Here is an example of my code:
function ceiling2(number) {
var ceiling2;
return ceiling2 = Math.ceil(number*100)/100;
}
//Totals
function lD23Total (e){
var app = UiApp.getActiveApplication();
var tB1v = parseInt(e.parameter.TextBox1);
var tB9v = parseInt(e.parameter.TextBox9);
var tB17v = parseInt(e.parameter.TextBox17);
var tB25v = parseInt(e.parameter.TextBox25);
var tB33v = parseInt(e.parameter.TextBox33);
var tB41v = parseInt(e.parameter.TextBox41);
var tB49v = parseInt(e.parameter.TextBox49);
var lD23 = app.getElementById("LabelD23").setStyleAttribute('fontWeight','bold');
var lD23T = tB1v + tB9v + tB17v + tB25v + tB33v + tB41v + tB49v;
lD23.setText("$ " + ceiling2(lD23T));
var app = UiApp.getActiveApplication();
app.close();
return app;
}
Currently it returns a rounded number.
I appreciate an suggestions you may offer!
Jon
The function parseInt() will convert the value to an integer, dropping the values after the decimal. Use parseFloat() instead.
I think your function is just fine...
if you remove the parseInt() and replace it either with parseFloat()as suggested by Eric or by Number() it should work...
if not then the problem might come from the way numbers are written:
If you used 26,4567 but you should use 26.4567 with a dot as separator in place of a comma.
Could you try and keep us informed ?
regards,
Serge
Or you can use this before sending to your function:
var newnumber=Number(number.toString().replace(",","."));// convert to string, replace comma with dot and set as number again.
and your function will work in both cases

Categories

Resources