Problem: wrong time and timezone .getValue() from cell with format time
The bug occurs in old spreadsheets from 2017, but not a spreadsheet from 2022 january or new spreadsheets. update: it did appear in a new sheet as well
What steps will reproduce the problem?
Spreadsheet settings -> timezone GMT+1 (your current timezone)
in cell A1 write 20:00:00
set format cell A1 to "time"
execute this function in google apps script
function showTimeInCellA1() {
const date = SpreadsheetApp.getActiveSheet().getRange("A1").getValue();
SpreadsheetApp.getUi().alert("date in A1 is " + date);
}
Problem: it will alert "date in A1 is Sat Dec 30 1899 19:09:21 GMT+0009"
Expected: I expected time 20:00:00 and GMT+1(because settings spreadsheet are GMT+1)
This appears to be a bug!
Leaving this here for future readers as I think this may have been reported by OP.
There is already a report on Google's Issue Tracker which detail the same kind of behaviour:
wrong time and timezone .getValue() from cell with format time
Google does seem to know about this issue but you can also hit the ☆ next to the issue number in the top left of the page so to let Google know more people are encountering the behaviour so it is more likely to be seen to faster.
A workaround could be to add some years and use the time value of the new date object. I did not examine the exact number of years to be added in order to get valid time information - just tried to get past 1970 which worked for me.
var val2=new Date(val).getTime()+1000*60*60*24*365.25*72 // add ~72 years
Logger.log(new Date(val2))
The value of the current cell in Google Sheets is "8:00:00 AM"
A helper function was used to add the time to a given date:
function utils_buildDate(date,time){
var d=new Date(date);
// +-----------------------------------------------------------------
// | fix time value problem (no date is given in sheet)
// | https://issuetracker.google.com/issues/230650549?pli=1
time=new Date(time).getTime()+1000*60*60*24*365.25*72 // add ~72 years
// +-----------------------------------------------------------------
d.setHours(new Date(time).getHours());
d.setMinutes(new Date(time).getMinutes());
d.setSeconds(new Date(time).getSeconds());
return d;
}
Related
I'm looking for more of a pointer to some documentation of a method here rather than an exact solution, I'm happy with JavaScript, haven't done much Apps Script and I'm moderate to OK familiar with Google Sheets functions but far from expert.
I have part of a Google Sheet with some date specific data on it like this:
Date
Some-Value
1 Jan 2023
123
15 Jan 2023
456
... etc
In another part of a sheet I have a cell with the current value of Some-Value. This cell in fact contains a formula that totals a column on another sheet for the values. In case it's not blindingly obvious, these dates are in fact sprint end dates and the Some-Value is a count of story points extracted from JIRA. So sort of like this:
Current Value of Some-Value
345
On exactly the date in the Date column I want to copy the value from the "Current Value of Some Value" cell into the cell in the "Some Value" column adjacent to that date. I don't care if that copy happens only once on that day, or several times on that day, or every hour on that day, or whatever. I just want it to happen at least once, automatically.
Should I be looking at an Apps Script function to do this, and roughly how should I do that? Or is there a simpler way of using some Google Sheets function to copy that cell?
You could potentially do this with formulas if you are willing to enable iterative calculation for your sheet. In that case, you could then write something like =if(A2=today(),currentValueCell,B2) (I'm assuming your Date/Some-value table is in A1:Bx of a sheet and you are placing the above in B2). This will return the current value only if the date matches, and then when the dates no longer match will just maintain whatever value is already present in the cell.
EDIT
Ah yes, I forgot that the initial state of a self-referencing IF is zero (rather than null) until a TRUE occurs. Try =if(A2=today(),currentValueCell,if(B2<>0,B2,)) to hide the initial zero generated when the date in A2 is not equal to TODAY().
If you need to copy a value than then it's going to be changed or erased, yes, you'll need an AppScript. If you already know something, you'll more than able to set a simple function to do it.
You can look into Installable Triggers that will help you to set when and how frequently you want your script to be fired; and it will notify you if there are errors in any of that executions.
Sometimes, matching dates can be tricky, more if you have them previously written. If you have to do a timestamp, then you'll probably succeed at first. Just for have it handy: https://developers.google.com/google-ads/scripts/docs/features/dates
Remember to always use Logger.log() to track the progress of your code and what it's returning. Good luck and here you can always ask for specific struggles you may find!
(I'm no expert at programming by far, since it's copying only a value, you may find useful to record macros and watch them to learn how to copy in the formats you need - only values, paste format, etc. - if you don't copy, you can also research in .getValue() and .setValue() )
In case anyone else comes across this in future, here is the somewhat creaky Apps Script function I developed to do this. It's my first Google Apps Script function so feel free to tear it to shreds.
I then added a trigger to run this function weekly, which was easier than I had thought -- a bit of google searching for Apps Script time based triggers found me the answer.
Nonetheless thanks to the people who answered earlier because the clues you gave me helped me find the answer in the end.
function updateUnderTest() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = activeSheet.getSheetByName('Supporting Data');
// I12 is the cell that gets updated daily with the story point count
var value = sourceSheet.getRange('I12').getValue();
// D3:E27 is the range containing date : value pairs
var data = sourceSheet.getRange("D3:E27").getValues();
// epochNow will be the current epoch time, in milliseconds
var epochNow = new Date().valueOf();
// Look through the data range to find a matching date
for (nn=0;nn<data.length;++nn) {
// If a match is found to the nearest day, break the loop
if ((data[nn][0].valueOf() < epochNow) && ((epochNow - data[nn][0].valueOf()) < (24*3600*1000) )) {break};
}
// only update if we found a match
if (nn < 24) {
sourceSheet.getRange(nn+3, 5).setValue(value);
}
}
I am trying to write a script to add events from Spreadsheet to Calendar. I found the time of added events is always 1 hour off. I checked the time zone settings and here's what I found.
Calendar: (GMT-04:00) Eastern Time
Spreadsheet: (GMT-05:00) Eastern Time
Script: (GMT-05:00) Eastern Time
So they are all Eastern Time, but the Calendar uses the Daylight Savings Time while the Spreadsheet and Script.
I know I can manually adjust GMT every time DST changes so that the resulting time is right. But is there a better way, so that I can set and forget?
Instead of hardcoding the timezone with GMT-04:00 use the literal expression of your geographic area (aka Canonical ID) as defined in this standard : Joda.org
this is what Google Apps Script is using.
You can also get that more simply using
SpreadsheetApp.getActive().getSpreadsheetTimeZone()
or from the calendar object : calendar.getTimeZone()
all these parameters will handle daylight savings automatically, which is not the case for the GMT+xx:xx method.
You shouldn't have any problem as long as both are on the same timezone. Calendars have a setTimeZone(timeZone) method and spreadsheets have a setSpreadsheetTimeZone(timeZone) method so it is easy to synchronize both
EDIT
Following comment
Since you seem to combine date and time in a unique date object and that the daylight saving puts you into trouble (because "pure time" values in spreadsheets are converted to a date JavaScript object automatically and with summer time correction), below is a small code that I use to workaround this issue. I added a few logs to show intermediate values;
function combineDateAndTime(){
// in this example cell A1 has a date and cell B1 has time
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
var dateOnly = sh.getRange('A1').getValue();
var timeOnly = sh.getRange('B1').getValue();
Logger.log('dateOnly object is : '+dateOnly+'\ntimeOnly object is : '+timeOnly);
var hours = Number(Utilities.formatDate(timeOnly, 'GMT'+timeOnly.toString().split('GMT')[1],'hh'));
var minutes = timeOnly.getMinutes();
var completeDateAndTime = new Date(dateOnly.setHours(hours,minutes,0,0));
Logger.log('completeDateAndTime is : '+completeDateAndTime);
}
Note : there are other ways to retrieve hour values, see this post for example.
I have a Google form to collect info on people leaving the organisation. One of the questions is 'What date and what time do they leave' The response is in the format dd/mm/yyyy, hh:mm. so a typical response would be 24/04/2015 17:00:00, and that's what I see in the Form responses 1 worksheet when the form is submitted.
I need to add the day of the week and copy the information into another worksheet within the spreadsheet, so I use
var leaveDate = inputSheet.getRange("G" + lastRow).getValue();
var leaveDateTime = Utilities.formatDate(leaveDate, "GMT", "EEE dd-MM-yyyy hh:mm:ss");
The issue I'm seeing is that when I paste the value the time is changing, and what gets pasted is
Fri 24-04-2015 04:00:00
Can anyone explain why this is happening and what I can do to resolve it?
Thanks
Apps Script converts date types to the time zone set up in the script editor. In the script editor, you need to set the time zone, even if you've set it in the spreadsheet.
Set the time zone to your local time zone.
Make sure the time zone in your spreadsheet, and the time zone in your script editor match.
If you have multiple editors of the spreadsheet in multiple time zones, and the other users have set the time to their local time, then obviously, their time and your time won't be the same. If someone left the organization on the other side of the world, at 4pm their time, they didn't leave the organziation at 4pm your time. You could assume that if the spreadsheet states 4pm, that it was their local time, and convert the time. In that case, you'd need to know the time zone of every time entry that is made, and then adjust it as necessary.
Try:
...
// var leaveDateTime = Utilities.formatDate(leaveDate, "GMT", "EEE dd-MM-yyyy hh:mm:ss");
var leaveDateTime = Utilities.formatDate(leaveDate, "GMT", "EEE dd-MM-yyyy HH:mm:ss");
...
UPDATE
Thanks to #sandy-good and #wchiquito for pointing me in the right direction. There were 2 issues. First issue is using hh instead of HH. The second issue is that we are on GMT+1 at the moment, and will be until end October, at which point we go back to GMT! As I don't want to code around that I'm going to simplify it by dropping the day, which then means I don't have to reformat the date.
To be frank I'm a complete newb at scripting and I have went as far as submitting a request to Googles support and was directed here.
What I'm needing is to be able to update a cell in a spreadsheet every day at a certain time, also I need to be able to do this multiple times daily.
Basically what I need is for is at 8:00 PM I need the values from B4 down to be copied into D4 down. When tried using the basic functions in Google the most that can be obtained is for the minute of 8:00 PM it will update then at 8:00 1 it goes back to 0.
If I hadn't looked for days I wouldn't be asking for help. I apologize for my newbness.
A screenshot of the sheet I'm working with can be found via my Google Drive below.
https://drive.google.com/file/d/0B2GuBHPLz-Z_TWw2ZmtxNWJ0bkU/view?usp=sharing
You need to set up a time-based trigger that runs around 8 PM everyday and it should call the method that will update the cell.
function addTrigger() {
ScriptApp.newTrigger("updateCell").timeBased().atHour(20).everyDays(1).create();
}
function updateCell() {
var url = "<SPREADSHEET URL HERE>";
var cell = "<CELL in A1 Notation>";
SpreadsheetApp.openByUrl(url).getRange(cell).setValue(new Date());
}
You'll have to run the addTrigger method once for setting this up.
Here is my code:
function calEvent(){
var arrivalDate = "06/10/2013";
var departureDate = "06/18/2013";
var start = new Date(arrivalDate);
var end = new Date(departureDate);
var cal = CalendarApp.getCalendarById('id487g3esn088a00omqa99ugv0#group.calendar.google.com');
cal.createEvent('Apollo 11 Landing',start,end);
}
When I run this it will create the event in the correct calendar however it will only be from June 10 thru June 17. I need the event to cover June 10 - June 18.
I have checked the Timezone setting and the spreadsheet, script and calendar are all on the same time zone (Mountain Time GMT-7)
How can I get this seemingly simple code to set the event on the correct dates? I've tried several date formatting (utilities.formatDate) but can't seem to get the correct format.
Thanks in advance.
How to use timeZone of calendar to set timeZone for date object
I posed the above question a couple a weeks ago, and came up with a working solution. Not sure if it is the best or not, but you can look over and see if it helps. In working on a solution for my question I noticed several things. The script definitely uses the script timezone to create a date object. But when it post to a calendar it adjust the date to executors default calendar timezone not the timezone of the calendar you're writing too. So if a user's default calendar timezone is different from the calendar being written to you will get all kind of crazy time's
So the function gasTimezoneOffset() that is listed in the above question was my solution for this.
Hope this helps.