Using dates in Google Sheets - google-apps-script

Dates are giving a bit of trouble in Google Sheets. I'm basically trying to subtract dates but it's not working. However first, I'm trying to understand how Dates work. Here's an example of an odd behavior with dates.
function addDates(sheet)
{
var prevDateCurrYear = new Date();
Logger.log(prevDateCurrYear);
Logger.log(prevDateCurrYear.getMonth()+' '+prevDateCurrYear.getDay()+' '+prevDateCurrYear.getYear());
}
This is the Log
[15-02-03 18:15:21:631 EST] Tue Feb 03 18:15:21 GMT-05:00 2015
[15-02-03 18:15:21:632 EST] 1 2 2015
The getMonth and getDay doesn't seem to work. It should be pulling 2 and 3 but instead pulls 1 and 2. Why is this happening?
I'm using this documentation: https://developers.google.com/apps-script/reference/contacts/date-field

Actually getMonth and getDay are Java script methods. The way the getMonth and getDay works different in Javascript. You can refer to these pages for more information.
http://www.w3schools.com/jsref/jsref_getday.asp
http://www.w3schools.com/jsref/jsref_getmonth.asp
Hope that helps!

Couple things to consider.
1. Set the Time Zone in your script Project Properties. File, Project Properties.
2. Using Utilities.formatDate() can relieve a lot of headaches as you can standardize your dates to your needs.
3. getDay() and getDate() return "day of the week (i.e. 1-7)" and "the date of the month (i.e. 1-31)", respectively.
here is some more details about dates to clarify:
function addDates() {
var prevDateCurrYear = new Date();
var year = Utilities.formatDate(prevDateCurrYear, "America/Denver", "yyyy");
var date = Utilities.formatDate(prevDateCurrYear, "America/Denver", "d");
var month = Utilities.formatDate(prevDateCurrYear, "America/Denver", "M");
Logger.log("\nUnformatted prevDateCurrYear: "+prevDateCurrYear+
"\n\nYour original log:\nprevDateCurrYear.getMonth(): "+prevDateCurrYear.getMonth()+"\n"+
"prevDateCurrYear.getDay(): "+prevDateCurrYear.getDay()+"\n"+
"prevDateCurrYear.getYear(): "+prevDateCurrYear.getYear()+"\n"+
"\nUsing Utilites.formatDate():\nmonth: "+month+"\ndate: "+date+"\nyear: "+year+
"\nUtilities.formatDate(prevDateCurrYear, \"America/Denver\", \"M d yyyy\"): "
+Utilities.formatDate(prevDateCurrYear, "America/Denver", "M d yyyy"));
}
Log:
Unformatted prevDateCurrYear: Thu Feb 18 2016 11:29:42 GMT-0700 (MST)
Your original log:
prevDateCurrYear.getMonth(): 1
prevDateCurrYear.getDay(): 4
prevDateCurrYear.getYear(): 2016
Using 'Utilites.formatDate()`:
month: 2
date: 18
year: 2016
Utilities.formatDate(prevDateCurrYear, "America/Denver", "M d yyyy"): 2 18 2016

Related

How to get google sheet's cell values as is using google script

I'm about to use google sheet as my database for my android app small project. I'm using Google Script to handle the request from my app.
In my google sheet, I store;
A2:A = date as dd/mm/yyyy e.g 21/12/2019 but
the display format is dd-MMM e.g 21-Dec
C2:D = time as hh:mm:ss e.g 21:00:00 but
the display format is hh:mm e.g 21:00
Yes, I need a different format for the display and input.
My google sheet:
When I use google script to get a value of the cell, it seems that it is reformatted
the date looks like this: Sat Jan 01 2019 00:00:00 GMT+0700 (ICT)
the time the other hand, change in value a bit. 20:00:00 to 19:52:48
Is there any function to get cell real values as text without being reformatted?
The only thing that I can think of is instead of using getValues(), I can use getDisplayValues(). The values will not be reformatted, but it is not a solution for me, as it will take the display format.
Snippet of my code:
function updateData(e, sheet) {
var tgl = e.parameter.tgl;
var dtg = e.parameter.dtg;
var plg = e.parameter.plg;
var lbr = e.parameter.lbr;
var rangeHead = sheet.getRange("A2:A");
var valuesHead = rangeHead.getValues();
var rangeFirst = sheet.getRange("C2:D")
var valuesFirst = rangeFirst.getValues();
var rangeSecond = sheet.getRange("G2:G")
var valuesSecond = rangeSecond.getValues();
for (var i = 0; i < valuesHead.length; i++) {
if (valuesHead[i][0] === tgl) {
if(dtg!="null") { valuesFirst[i][0] = dtg; }
if(plg!="null") { valuesFirst[i][1] = plg; }
if(lbr!="null") { valuesSecond[i][0] = lbr; }
break;
}
}
rangeFirst.setValues(valuesFirst);
rangeSecond.setValues(valuesSecond);
}
The code won't work as I will comparing 21/12/2019 with Sat Jan 01 2019 00:00:00 GMT+0700 (GMT).
[UPDATE 1]:
Thank you P-Burke for the enlightenment. Now, I have an idea to solve the date problem. I know that the script pulls the date as date object, but I am unaware that it also saves as a date object. (hehe my bad) I don't realize it as there is no autocomplete when I call values[0][0]. of course, as it recognizes the object type at the run time.
So, my workaround will be; I will call getDate, getMonth+1, and getYear. After that, I will compare with my parameter freely.
Though, the time cell still a bit confusing for me. the time offset is 18 minutes 12 seconds. I don't think it's because of timezone different and my computer clock. the timezone different is too big and I 've made sure that the script, spreadsheet, and local timezone all the same. My computer clock is also only a minute less behind.
[UPDATE 2]:
Alright, enough with the confusion. It seemed that the script converts the time to Date object respect to my local timezone. I got this answer from another thread. So, actually, my local timezone changes many times and some of them have offset smaller than hours unit (one of the timezones used in my area is UTC +7:07:12h). The only source documenting those changes I could find is from https://www.timeanddate.com/time/zone/indonesia/jakarta. Finally, I gave up. For my goodness sake, I will just use getDisplayValue and ignore the seconds. Unless you guys have any other workaround, I will be so grateful.
Thank you once again to the community.
Firstly, and I don't know if this is related to your issue, but the spreadsheet and the script each have their own timezone setting:
Spreadsheet: File >> Spreadsheet Settings >> Time Zone.
Script: File >> Project Properties >> Time Zone.
And if these are different that can lead to confusion. One answer, if all your users are in the same timezone, is to set them to the same. Alternatively these can be determined from within your script as described here, and logic included to handle any differences. I don't understand the few minutes time difference, perhaps your PC clock is inaccurate?
The other point, which I think is more relevant to your question is that you effectively have multiple date/time formats in play. The picture below shows that in the spreadsheet times are edited in one format (02/01/2019 09:00:00), but displayed in whatever format is defined for the cell using the format menu. Yet when the cell values are pulled into a script using getValues() and displayed they appear as follows: Values: [[Thu Jan 31 09:00:00 GMT+00:00 2019, Wed Jan 02 09:00:00 GMT+00:00 2019]].
Yet in the code below, values[0][0] and values[0][1] are actually JavaScript Date() objects and can be compared in the usual way, alternatively they can be reformatted into whatever string format you require as illustrated in the code below:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var ws = ss.getActiveSheet();
var input_range = ws.getRange("A1:B1");
var values = [];
values = input_range.getValues(); // Returns a multi-dimensional array, hence [0][0] to access.
Logger.log("Values: %s", values);
// As Date() objects the usual methods are available.
Logger.log("Date().getMonth(): %s",values[0][0].getMonth());
Logger.log("Date().getYear(): %s",values[0][1].getYear());
// This formats the date as Greenwich Mean Time in the format
// year-month-dateThour-minute-second.
var formattedDate = Utilities.formatDate(values[0][0], "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'");
Logger.log(formattedDate);
formattedDate = Utilities.formatDate(values[0][1], "GMT", "yyyy-MM-dd'T'HH:mm:ss'Z'");
Logger.log(formattedDate);
}
Logger.log output:
[19-01-31 11:43:17:635 GMT] Values: [[Thu Jan 31 09:00:00 GMT+00:00 2019, Wed Jan 02 09:00:00 GMT+00:00 2019]]
[19-01-31 11:43:17:636 GMT] Date().getMonth(): 0.0
[19-01-31 11:43:17:637 GMT] Date().getYear(): 2019.0
[19-01-31 11:43:17:638 GMT] 2019-01-31T09:00:00Z
[19-01-31 11:43:17:638 GMT] 2019-01-02T09:00:00Z

Apps Script - Formatting the current date for timestamp

I wish to format the current date as "yyyy/MM/dd HH:mm". formatDate allows me to format the date but I need to specify a timezone, per the following:
Utilities.formatDate(new Date(), "GMT", "yyyy/MM/dd HH:mm")
This is almost what I want, but I want the result to be BST or GMT, as appropriate to the calendar. What timezone should I specify to get the answer without further manipulation of the text date? (I do have a clumsy workaround). The problem caught me out with a timed batched process that runs at midnight upon our recent BST clock change where timestamps of 23:00 the previous day were applied.
In your script properties, make sure you've selected the correct time zone. Then, in your script, instead of using "GMT", use Session.getScriptTimeZone().
function test() {
var date1 = new Date("March 10, 2018 10:00");
var date2 = new Date("March 11, 2018 10:00");
Logger.log(date1); // Sat Mar 10 10:00:00 GMT-05:00 2018
Logger.log(Utilities.formatDate(date1, Session.getScriptTimeZone(), "yyyy/MM/dd HH:mm")); // 2018/03/10 10:00
Logger.log(date2); // Sun Mar 11 10:00:00 GMT-04:00 2018
Logger.log(Utilities.formatDate(date2, Session.getScriptTimeZone(), "yyyy/MM/dd HH:mm")); // 2018/03/11 10:00
}
In the script editor, go to File > Project properties and set your time zone. (I used Eastern time for mine.)

Utilities.formatDate returning wrong week number

In Google Script I have the following code:
var myDate = new Date(sheet.getRange(3,1).getValue());
var year = Utilities.formatDate(myDate, "Europe/Amsterdam", 'dd-MM-yyyy');
var weekyear = Utilities.formatDate(myDate, "Europe/Amsterdam", 'dd-MM-YYYY');
var week = Utilities.formatDate(myDate, "Europe/Amsterdam", 'w');
When I insert 30-12-2015 as date, the result will be.
// year: 30-12-2015
// weekyear: 30-12-201**6**
// week: 1
In my local timezone, it should be week number 53. Not 1.
If I calculate the week in ISO 8601, the result is 52.
Strange, isn't it?
Edited:
New attempt, with this code
var cursus_datum = sheet.getRange(3,1).getValue();
Logger.log('type of data: ' + typeof cursus_datum);
Logger.log(cursus_datum);
Logger.log(Utilities.formatDate(cursus_datum, SpreadsheetApp.getActive().getSpreadsheetTimeZone(), "d-MM-y HH:mm"));
Logger.log(Utilities.formatDate(cursus_datum, SpreadsheetApp.getActive().getSpreadsheetTimeZone(), "w"));
This results in
// type of data: object
// Wed Dec 30 09:00:00 GMT+01:00 2015
// 30-12-2015 00:00 which is perfect
// 1 which is **not** correct.
The wrong week is the bug.
The Utilities.formatDate documentation states that it uses Java SimpleDateFormat - I have a feeling this might be the cause of the problem as they are Locale sensitive and I would take a guess it will be using the default US locale (I don't think passing in the timezone changes the locale). The problem is the US locale calendar has getFirstDayOfWeek() = 1 (SUNDAY) and getMinimalDaysInFirstWeek() = 1. And for ISO 8601 you need the settings 2 and 4 respectively. I think you're better off sticking to the Javascript code you linked to if you want to work with week years.
new Date() will accept a few different parameter configurations, but you still need to make sure that the parameters are correct. You can't just plug anything into new Date() If the variable is already a date type, then there is no point using new Date(). You can test for the data type with typeof.
var dateFromSheet = sheet.getRange(3,1).getValue();
Logger.log('type of data: ' + typeof dateFromSheet);
If the data type is a string, it must be in a valid date string format. There are a few different formats. But, again, you need to use a valid format.
ISO 8601 syntax "YYYY-MM-DD" or "YYYY-MM" or "YYYY" or "YYYY-MM-DDTHH:MM:SS"
Long Date syntax - Year, month and day can be in any order: "Mar 7 2015" or "2015 Mar 7", and Month can be written in full: "2015 March 7"
Short dates - "/" or "-" can be used. "MM/DD/YYYY" or "YYYY/MM/DD" NOTE: You can not use "DD/MM/YYYY"
Full Date Format - "Wed Mar DD YYYY HH:MM:SS GMT+0100 (W. Europe Standard Time)"
This is what I did:
function getCurrentCalendarWeek(){
let date = new Date();
let weekNum = Utilities.formatDate(date, "Europe/Berlin", "w") - 1;
if (weekNum === 0){
weekNum = 1
}
return weekNum
}

Utilities function in Google App Scripts not working

Function Utilities.formatDate in Google App Scripts is not working correct for date in year 2013
Example-
date = Tue Dec 31 2013 18:43:12 GMT+0530 (IST)
after formatting it in YYYYMMdd format
using code-
Utilities.formatDate(date, "IST" ,"YYYYMMdd"))
result was- 20**14**1231
In the above result year is expected to be 2013 as per above mentioned date.
The same code is working correct for date in 2012 and 2014.
Just change your pattern from YYYY to yyyy (lower case) and it will work, check this:
function myFunction() {
var date = new Date("Tue Dec 31 2013 18:43:12 GMT+0530 (IST)");
//after formatting it in YYYYMMdd format
var format = Utilities.formatDate(date,"IST", "yyyyMMdd");
Logger.log(format);
}

Trying to subtract 5 days from a defined date - Google App Script

I'm trying to write a script which is supposed to send out an email and create two calender entries when submitting a form. To be honest, this is my first script and I am very happy that the email is send out and the calender entries are working as well. The thing which gives me a headache is to subtract 5 days (actually x days) from a defined date.
First I thought I could simply do something like
var liveday = e.values[2];
var newday = liveday-5;
well, this didn't work :-)
I tried more:
var newtime = new Date(liveday);
var yr = newtime.getYear();
var dt = newtime.getDay();
var mt = newtime.getMonth();
var dtnew = dtnew.setDate(mt, dt-5, yr);
But here I received 1418256000000 whereas liveday = 12/01/2014. Not sure why days were added, rather than subtracted.
I am quite confused here and the answer can't be that hard.
I just want to subtract 5 days from 12/01/2014 to receive 11/27/2014.
Thanks for having a look
the comment sends you to a rather complicated serie of codes... there is a far more simple way to get that, here is the code :
function test() {
Logger.log('today= '+new Date()+' and 5 days ago is '+subDaysFromDate(new Date(),5));
}
function subDaysFromDate(date,d){
// d = number of day ro substract and date = start date
var result = new Date(date.getTime()-d*(24*3600*1000));
return result
}
Logger result :
[13-11-18 23:39:50:364 CET] today= Mon Nov 18 2013 23:39:50 GMT+0100 (CET) and 5 days ago is Wed Nov 13 2013 23:39:50 GMT+0100 (CET)
if you want to get the date in the form dd/mm/yyyy use Utilities.formatDate(date, timeZone, 'dd/MM/yyyy), see doc here