Utilities.formatDate returning wrong week number - google-apps-script

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
}

Related

Date changes when setValues() is called

I have written a script for a client in a Spreadsheet whose time is GMT-5 while my TimeZone is GMT+5. The column H on the spreadsheet's tab has a value as date without any time factor e.g. 01/25/2019.
On the start of script function I am setting the format of column like under the following .setNumberFormat("MM/dd/yyyy"). Also note that I am working with .getDisplayValues() which returns me test for the Date column.
There is nowhere in the script I am explicitly updating DateValue its value. After manipulating some other values on the other column I happen to update the row by calling the .setValues([row]).
Then the date changes to 01/24/2019 and when I change the format to include time factor then it is like 01/24/2020 19:00:00.
Interesting point is it does not occur on my end where my timeZone is GMT+5. Even though I changed the Spreadsheet's Timezone to GMT-5 and on my system as well but still it doesn't occur on my end but on the client machine.
The runtime version of the script is:
"runtimeVersion": "V8"
This can happen when the script time zone and spreadsheet time zone are different and you format the date object
I cannot reproduce your exact situation from the information you provided, but I invite you to do the following test:
Set your spreadsheet timezone to any timezone that is ahead of your script time zone
Set cell A1 of your active sheet to =today()
Run the following code:
function myFunction(){
var displayDate = SpreadsheetApp.getActiveSheet().getRange("A1").getDisplayValue();
Logger.log("displayDate: " + displayDate);
var date = SpreadsheetApp.getActiveSheet().getRange("A1").getValue();
Logger.log("actual date retrieved by Apps Script: " + date);
var timeZone = Session.getScriptTimeZone();
Logger.log("ScriptTimeZone: " + timeZone);
var timezone2 = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
Logger.log("SpreadsheetTimeZone: " + timezone2);
var newDate = Utilities.formatDate(date, timeZone, "MM/dd/yyyy");
Logger.log("formatted date that will be set back to the spreadsheet: " + newDate);
SpreadsheetApp.getActiveSheet().getRange("A1").setValue(newDate);
}
function updatePatientTransactions(transactionSheetValues, patientNam, insuranceName) {
var tempRow = [];
for(var i= start; i<= end-2; i++) {
tempRow = transactionSheetValues[i];
tempRow[0] = patientName;
tempRow[3] = insuranceName;
transactionSheet.getRange(i+2,1,1,transactionSheet.getLastColumn()).setValues([tempRow]);
}
}
Observe the logs and the output
Sample logs:
Stackdriver logs
Jun 8, 2020, 1:03:00 PM Info displayDate: 6/8/2020
Jun 8, 2020, 1:03:01 PM Info actual date retrieved by Apps Script: Sun Jun 07 2020 23:00:00 GMT+0200 (Central European Summer Time)
Jun 8, 2020, 1:03:01 PM Info ScriptTimeZone: Europe/Paris
Jun 8, 2020, 1:03:01 PM Info SpreadsheetTimeZone: Europe/Athens
Jun 8, 2020, 1:03:01 PM Info formatted date that will be set back to the spreadsheet: 06/07/2020
so the date will be set back to yesterday.
Why?
When you retrieve a value that is formatted as Date and not Date Time, that is if the time is not set - Apps Script automatically sets it to midnight.
When it is the 8th of June midnight in Athens, it is the 7th of June 23:00 o'clock in Paris
This is why the conversion from a spreadsheet timezone to a script timezone lying behind will lead to a date change
Now, if you format the date value as a date string or process it otherwise, the informaiton about the original timezone might get lost and when you set the datestring back to the spreadsheet, you will set back the Apps Script date - different from the spreadsheet date - so be careful!

Getting day of the week not working when using setNumberFormat

I would like programably enter the date into a cell and format it to include the Day of the week (Mon, Tue, Wed,...). If I use the .setNumberFormat method (which I would prefer to do because it keeps the info as a date), the simpleDateFormat for Day of the week does not work. If I use Utilities.formatDate I can use 'EEE, MM/dd' and it will show up correctly, but I lose the date format.
function setformat(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var lab = ss.getSheetByName("test2");
// This is what I want to use but the day of the week 'EEE' doesn't work
var todaySNF = new Date();
lab.getRange("a1").setValue(todaySNF);
lab.getRange("a1").setNumberFormat('EEE, MM/dd'); // Should read Wed, 09/23 but reads EEE, 09/23 instead.
var cellA1asDate = new Date(lab.getRange("a1").getValue());
Logger.log(cellA1asDate);}
use this instead :
lab.getRange("a1").setNumberFormat('DDD, MM/dd');

Utilities.formatDate Date not set correct

I have a date stored as follows:
existingDate = Wed Apr 30 2014 00:00:00 GMT+0100 (BST)
When I use Utilities.formatDate to format the date the date is changed to the day before.
var formattedDate = Utilities.formatDate(new Date(existingDate), "GMT", "dd/MM/yyyy");
the formatted date is then set to 29/04/2014 and not 30/04/2014.
Has anyone else seen this behavior.
Utilities.formatDate seems to be working fine.
You have Apr 30 midnight in GMT-1 but then you tell it to format this date in a different timezone GMT, or more explicity GMT-0. The expected result is indeed Apr 29 23h.
The second parameter in Utilities.formatDate must be the timezone you desire.
There are some other issues with this google script.
If I want the timezone AEST but only have the date in the form of 1/27/2017, then Utilities.formatDate("1/27/2017","AEST","yyyy-MM-dd") will return a value of 2017-01-26, a day before it should be! However if I have a time with it such as "1/27/2017 12:00:00" then it returns the correct day. However if I use "GMT+11" as the timezone even without a time on the end if returns the correct day.
Example -
Logger.log('Example 1='+Utilities.formatDate(new Date("1/27/2017"),"AEST","yyyy-MM-dd"));
Logger.log('Example 2='+Utilities.formatDate(new Date("1/27/2017 12:00:00"),"AEST","yyyy-MM-dd"));
Logger.log('Example 3='+Utilities.formatDate(new Date("1/27/2017"),"GMT+11","yyyy-MM-dd"));
Output -
Example 1=2017-01-26
Example 2=2017-01-27
Example 3=2017-01-27
A workaround when reading a date from a spreadsheet cell that does not have a time is to add a time and when using a timezone like "AEST" or similar, something like this -
var displayDate = sheet.getRange(a1Notation).getDisplayValue(); // Not .getValue();
Logger.log(Utilities.formatDate(new Date(displayDate + " 12:00:00"), "AEST", "yyyy-MM-dd"));
However "GMT+11" would be easier because you don't need to add a time.

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

Google SpreadSheet Custom Date Format

I'm looking for a easy formula to generate this type of Date Format:
10:35 PM August 12th 2013
hh:mm AM/PM Month dd yyyy
It's for the MarketMeSuite CSV scheduling utility that only excepts that format when uploading scheduled tweets.
Yes this format is possible using the Utilities.formatDate() utility. Please see Oracles Class SimpleDateFormat documentation for java as this uses the same formats. You should be able to get your desired format using the below formatting.
h:mm a MMMMM d yyyy
The only issues would be with the th or nd or rd or st after the date. But you could use some if statements to format that depending on the number, I'll let you work on that :)
The final string of the above would be -
9:16 PM April 15 2013
So the final date object creation would be.
Utilities.formatDate(new Date(), "GMT", "h:mm a MMMMM d yyyy")
EDIT
I've just realised you might not be talking about getting this format in a script but actually just calling it in a cell. If so you still need to create a custom function, so add the below code to a new script.
function getDate() {
var date = Utilities.formatDate(new Date(), "GMT", "h:mm a MMMMM d yyyy")
return date;
}
Then you can call it back in a cell with =getDate()