Converting Unix timestamp in Google App scripts - google-apps-script

I am new to Google App Script and am currently working on a project to help myself get familiar with it. My project has a part where I have to convert Unix Timestamp objects in nested JSON to human-readable time. As I don't know about converting timestamps in Google App scripts, I looked into the documentation and found "Utilities.formatDate()".
I tried using it on an example timestamp to see how it works and if it can be used for my needs. So I took a timestamp from the data and tried converting it with this code.
function blah () {
var tim = "1572401067";
var formattedDate = Utilities.formatDate(tim, "GMT+5:30", "MM-dd-yyyy HH:mm:ss");
Logger.log(formattedDate);
}
It ends with an error saying:
Cannot find method formatDate(string,string,string). (line 3, file "Code")Dismiss
What am I doing wrong here?

As your error message correctly describes, there is no such function as formatDate(string,string,string). The formatDate function that exists in GAS takes three parameters, where the first one is a Date, and the second and third ones are string's. A correction of your code could look like the following:
function blah() {
var tim = 1572401067;
var date = new Date(tim*1000);
var formattedDate = Utilities.formatDate(date, "GMT+5:30", "MM-dd-yyyy HH:mm:ss");
Logger.log(formattedDate);
}

Related

Is there a way to upload data from google sheets into calendar with concatenate data?

I am very new to using google script and is something I have taken interest in recently, with no prior knowledge I have so far been trying to self teach.
I have been playing around with a excel formula that will grab some data from a table on a daily basis and concatenate into a Date and Time format.
So I have the following data in a table:
Event : Time Start : Time End : Location : Description
Work Rota: 24/01/2022 08:30:00 : 24/01/2022 19:30:00 : (postcode) : Work Shift for today
The first row being headers and the 2nd row with the data I am trying to utilise.
The data in the Time Start and Time End column is data using the concatenate formula from another spreadsheet.
If this was not a concatenate formula, the correct Date and Time format for the script works fine, However I understand due to the concatenate formula, the data for the string format is not suitable for the createEvent function.
I have been playing around with google script to find a way to take this data and being able to import it into my google calendar and after struggling now for multiply days! I cannot find a resolution.
Is there a formula or process, that can read the data in column 2 and 3 to convert the data into a suitable format needed for the createevent function
This is the script I have been using.
function addEvents() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TEST");
var lr = ss.getLastRow();
var cal = CalendarApp.getCalendarById("calendarId");
var data = ss.getRange("A2:E" + lr).getValues();
for (var i = 0;i<data.length;i++){
cal.createEvent(data[i][0], data[i][1], data[i][2], {location: data[i][3], description: data[i][4]});
}
}
I appreciate anyone that may be able to help with this and thank you in advance!
I would have tried:
cal.createEvent(data[i][0], new Date(data[i][1]), new Date(data[i][2]), {location: data[i][3], description: data[i][4]});
}

Google App Script Card Service datepicker returns strange value

I have a simple script that creates and a Gmail Add on. Using Card Service the user can enter values that once submitted send the values to a Google Sheet. Everything works fine accept the date field which returns values such as {msSinceEpoch=1.6145568E12}. Attempts to use Utilities.formatDate fails to rectify this the default value of '1/1/1970' is returned. It is not clear to me why this is the case?
The Card Service includes the following for the date field:
section.addWidget(CardService.newDatePicker().setValueInMsSinceEpoch(Date.now())
.setFieldName('fieldD')
.setTitle(date));
This is followed by a standard action:
var action = CardService.newAction()
.setFunctionName('enterAction');
And a function which inserts the values in the Google Sheet:
function enterAction(e) {
var sheet = SpreadsheetApp.openById("SheetID").getActiveSheet();
....
var inputValues5 = e.formInput['fieldD'];
...
var values = [.....[inputValues5],...];
sheet.getRange(sheet.getLastRow() + 1,1,1,7).setValues([values]);
Any help appreciated.
can you try it like this?
section.addWidget(CardService.newDatePicker().setValueInMsSinceEpoch(new Date())
.setFieldName('fieldD')
.setTitle(date));
or
let newDate = new Date();
section.addWidget(CardService.newDatePicker().setValueInMsSinceEpoch(newDate)
.setFieldName('fieldD')
.setTitle(date));
Also not sure about the .setValueInMsSinceEpoch(), is there another function you can call?
1.6145568E12 is March 1st 2021 in milliseconds since the epoch (this is the expected format). I don't see your code for the formatDate statement, but something like this should work:
var fieldD = e.formInput['fieldD'];
var inputDate = new Date(fieldD.meetingTime.msSinceEpoch);
var inputValues5 = Utilities.formatDate(inputDate,
e.userTimezone.id,
"MM/dd/yyyy HH:mm:ss");

Google sheet custom function returns undefined Values sometimes

I have wrote a function to return latest weekly closing price of a stock in Google Sheet Apps Script.
But when using this in Google Sheets some cells are getting undefined data.
But the same cells are getting values correclty sometimes. Cant understand whats the problem here.
Also is there any option to debug my code when I execute the function from googlesheet cell?
function getWeeklyClosing(stockName){
var date =new Date()
var endDate = Utilities.formatDate(new Date(), "GMT+1", "yyyy/MM/dd")
var startDate = Utilities.formatDate(new Date(date.getTime()-10*(24*3600*1000)), "GMT+1", "yyyy/MM/dd")
var url ='https://www.quandl.com/api/v3/datasets/BSE/BOM'+stockName+'?start_date='+startDate+'&end_date='+endDate+'&collapse=weekly&api_key=3VCT1cPxzV5J4eGFwfvz';
var options =
{
'muteHttpExceptions': true,
"contentType" : "application/x-www-form-urlencoded",
"headers":{"Accept":"application/json"}
};
var response = JSON.parse(UrlFetchApp.fetch(url, options))
var weeklyEma=response.dataset.data[0][4];
return weeklyEma;
}
This answer corresponds to question rev 3 which had as title "How to use Promise in appscript?"
The title of the question is asking about an attempted solution rather than the actual problem ( an X-Y problem). The assumption that UrlFetchAp.fetch is asynchrous is wrong ( See Is google apps script synchronous?); the actual problem is getting undefined values on certain cells.
The solution will depend on the what you want to do when the the fetch response is
causing the undefined values. One alternative is to replace the undefined values by "" (an empty string) before sending the values to the spreadsheet that will cause having an empty cell on Google Sheets.
By the other hand, it could be that the API you are querying is not returning the JSON that you think, so first you have to understand it and then set the rules about how to send the result to the spreadsheet as not always it's possible to transform a JSON into a simple table structure.
UrlFetchApp.fetch(url) returns a HTTP response object. This response include a HTTP response code that could 200 for a successful fetch but could return other codes due to multiple reasons.
Some people in the past have suggest the use an algorithm called exponential back-off, like in this case Error message: "Cannot connect to Gmail". Be careful to not exceed the 30 seconds execution time limit.
Related
RESTful HTTP response codes

Why do I get Wrong timeZone conversion in google script using this code?

It's hours I'm struggling to know why I don't get correct timeZone using this script !
I've used moment.js and moment-timezone and followed instruction explained here:
Timezone conversion in a Google spreadsheet
google-spreadsheet/40324587
I am trying to convert timezones usign following script:
var DT_FORMAT = 'YYYY-MM-DD HH:mm:ss';
function fromUtc(dateTime, timeZone) {
var from = m.moment.utc(dateTime,
DT_FORMAT);//https://momentjs.com/timezone/docs/#/using-
timezones/parsing-in-zone/
return from.tz(timeZone).format(DT_FORMAT);
}
function toUtc(dateTime, timeZone) {
var from = m.moment.tz(dateTime, DT_FORMAT,
timeZone);//https://momentjs.com/timezone/docs/#/using-timezones/parsing-
in-zone/
return from.utc().format(DT_FORMAT);
}
function myFunction(datetimeString,timeZone,format) {
var moment = new Date(datetimeString);
return Utilities.formatDate(moment, timeZone, format)
}
In my spreadsheet, the first column is date and time in standard GMT and I'm going to change date and time to different TimeZones which I wrote in next columns. Even-though I'm getting the date and time, but it is incorrect and I don't know how to fix it.
Here is the link to Google sheet:
https://docs.google.com/spreadsheets/d/1Tc0G2daX9FYIL354iyOffd06BtNPx5v-40KE5RtwDB4/edit?usp=sharing
and here is the link to my script app:
https://script.google.com/d/1u54McW1HBm-A2alno1DWWTFwk-vdok8ljwKfI_5htAHK-XrMt554YGLn/edit?usp=sharing
Update (replying to comment) :
I use the function like this, I write in in a cell in spreadsheet:
=fromUtc(A2, D1)

Google Apps Script and RFC 3339 issue

In the Google reference documentation I found a short function to convert RFC3339 date string to a valid Date object. The code is very simple and goes like this :
function parseDate(string) {
var parts = string.split('T');
parts[0] = parts[0].replace(/-/g, '/');
return new Date(parts.join(' '));
}
The problem is that it does not work.(I'm surprised they publish a code that doesn't work... am I missing something ?)
I also had an issue while using JSON to stringify and parse dates because the JSON method returns a UTC value (a Z at the end) and because of that I lose the Time zone information. Google's code does not handle that issue either (even if it worked).
Below is a demo code I used to test it and a solution I wrote to get what I want. Not sure it's very efficient nor well written but at least I get the result I want (I'm executing this code in a script set to GMT+2, Belgium summer time).
I'm open to any suggestion to improve this code.(and that would be the subject of this question)
I added a lot of logs and comments in the code to make it as clear as possible :
function testJSONDate() {
Logger.log('starting value : "2016/3/31 12:00:00"');
var jsDate = JSON.stringify(new Date("2016/3/31 12:00:00"));// time is 12:00 I'm in GMT+2
Logger.log('JSON.stringify value : '+jsDate);
Logger.log('JSON parse jsDate : '+JSON.parse(jsDate)); // time is 10:00, UTC
var jsDateWithoutQuotes = jsDate.replace(/"/,'');
var date = parseDate(jsDateWithoutQuotes);
Logger.log('parsed RFC3339 date using Google\'s code : '+date); // does not return a valid date
var otherFunction = parseDate2(jsDateWithoutQuotes);
Logger.log('parsed RFC3339 date using other code : '+otherFunction); // does return a valid date in my TZ
}
function parseDate(string) {
var parts = string.split('T');
parts[0] = parts[0].replace(/-/g, '/');
return new Date(parts.join(' '));
}
function parseDate2(string) {
var refStr = new Date().toString();
var fus = Number(refStr.substr(refStr.indexOf('GMT')+4,2));
Logger.log('TZ offset = '+fus);
var parts = string.split('T');
parts[0] = parts[0].replace(/-/g, '/');
var t = parts[1].split(':');
return new Date(new Date(parts[0]).setHours(+t[0]+fus,+t[1],0));
}
Logger results :
EDIT following first answer
After a small change in the code I managed to get Google's snippet to work but the problem of time zone being lost still remains because of the way JSON converts JS date objects.
new code and logger result below:
function testJSONDate() {
Logger.log('starting value : 2016/3/31 12:00:00');
var jsDate = JSON.stringify(new Date("2016/3/31 12:00:00"));// time is 12:00 I'm in GMT+2
Logger.log('JSON.stringify value : '+jsDate);
Logger.log('JSON parse jsDate : '+JSON.parse(jsDate)); // time is 10:00, UTC
var jsDateWithoutQuotesAndMillisecAndZ = jsDate.replace(/"/g,'').split('.')[0];
Logger.log('jsDateWithoutQuotesAndMillisecAndZ = '+jsDateWithoutQuotesAndMillisecAndZ);
var date = parseDate(jsDateWithoutQuotesAndMillisecAndZ);
Logger.log('parsed RFC3339 date using Google\'s code : '+date); // does not return a valid date
var otherFunction = parseDate2(jsDateWithoutQuotesAndMillisecAndZ);
Logger.log('parsed RFC3339 date using other code : '+otherFunction); // does return a valid date in the right tz
}
You have taken a little helper function out of context. It was only meant as a stopgap device to get the strings returned by a particular API (Google Calendar API) to parse correctly in Apps Script. It is not any kind of universal date converter. A project member threw it together when filing an issue, and a follow-up message in that thread points out another detail that the function doesn't handle.
As of now, the date parser in Apps Script correctly parses the following formats:
function testdate() {
Logger.log(new Date("2016/03/31 10:00:00")); // local time
Logger.log(new Date("2016/03/31 10:00:00 +2:00")); // with given offset
Logger.log(new Date("2016-03-31T08:00:00.000Z")); // in UTC
}
Note that milliseconds are required for UTC timestamp, but are not allowed for the others.
What you do with a datetime string that needs to be parsed but is not one of the above, depends on its format. If you have 2016-03-31T10:00:00 (apparently, this is what Google Calendar API returns) and this is meant to be in local time, then you need exactly what the quoted parse function does: replace T by space and - by /. If the same string represents UTC time, one needs to add .000Z at the end. And so on.