Pergunta

So this is the first time I've ever encountered this error:

enter image description here

The system that received this error is a database/calendar-access UI I built. The system required extensive testing and I have never seen this error message before. Moreover, the system has been working perfectly for the past few months and my boss just sent me an email with a screenshot of the error.

It seemed at first that the issue was that the spreadsheets and scripts involved were not in the same time zone (times for events in the database were different from those on the calendar, so I figured it was time zones). I put everything in the same time zone and it seemed to work fine.

But then I tried it again, same error. I've done some investigating, and the following is coming up in my logs:

Event info: project_trainingDate1 --> Fri Mar 28 2014 00:00:00 GMT-0400 (EDT)
Event info: project_trainingDate2 --> Wed Mar 26 2014 19:00:00 GMT-0400 (EDT)

When clearly the UI has the following values:

enter image description here

Note: Dates that exist in the database set the UI DateBox to that date. That means that in the above example, trainingDate1 was in the database, so the DateBox.setDate() function is working as usual. However, dates such as trainingDate2 are those that I just created in the UI, meaning the DateBox widget had no previous value set. I imagine this is where the differences in time are coming from.

The second Date object is effectively newDate(UI value - 5 hours), which definitely poses a problem because the real date ends up a day behind when the time is set later.

I have not encountered this problem before, nor has my boss. This leads me to believe that there is a time zone issue somewhere, and that it has developed recently due to some change... however, I have double and triple-checked time zone settings on:

  1. All spreadsheets that have data being accessed in them by the script
  2. All script projects involved in this system
  3. All calendars on the account that use the system

All time zone settings are GMT -0500, as they have been for several months. It honestly makes no sense - I thought that the time zone was the issue, however it seems to be occurring with random values... see the following in the log of the UI-retreived values:

Event info: project_editingDate1 --> Sat Mar 29 2014 00:00:00 GMT-0400 (EDT)
Event info: project_editingDate2 --> Sat Mar 29 2014 19:00:00 GMT-0400 (EDT)
Event info: project_editingDate3 --> Sun Mar 30 2014 18:00:00 GMT-0400 (EDT)

Where the UI values were the following:

enter image description here

editingDate1 was a DateBox value that had its value set by the entry in the database. However, and even more bizarrely, editingDate2 and editingDate3 are an hour apart (as well as having both of their times wrong).

So the question: What type of time-zone or other issue related to DateBox is throwing off the values by 5 or 6 hours?

Keep in mind that no time zone settings have changed in this project, and the same calendar and code have been used without change for the past 3 months; now this bizarre behavior is occurring and I can't figure out why. Any thoughts?

P.S. - I know that script time zones differing from spreadsheet time zones can often be the source of errors, but I never encountered this 'DateBox returning expected hours -5' problem in my two weeks of extensive testing I did before I published the project, and every time zone setting is exactly the same as it was before.

P.P.S. - I am accessing the system from France, but I am logged into our work's admin account which hosts the system. My personal time zone difference shouldn't override the system time zone settings... but the difference in hours almost makes me believe that I'm just missing something really obvious.

Foi útil?

Solução

I understand it makes you angry (or nervous) but I guess there is no mistery in this error, just a simple misunderstanding of the calendar timezone settings.

You mentioned you tested this code extensively but I'm pretty sure you tested it on a period without daylight saving shift ..?

It appears that you defined your timezone using "GMT-0500" which seemed to be a good idea but in a few days we will be in summer time and this offset won't be the same anymore and the event that happen after the switching date are now out of date because of this change.

The solution is simple, use the timezone string as shown below, this parameter will take the hour value in the date object into account and adapt its value automatically based on summer/winter time.

This should be fairly easy to implement in your code.

replace "GMT-0500" with Session.getScriptTimeZone()

for a full explanation on this issue see this other recent post where I explain the different solutions.

Note also that the other answers forgot one small detail : the code is executed on Google's server, not in our browser, so the idea that a date is created in the timezone setting of the computer where it is created can be ambiguous... would it be our computer or Google's one ? good question ! A few years ago I spent a lot of time on this question, the former (and closed) Google help forum was full of posts on that subject because the Session.getScriptTimeZone() didn't exist at that time and it made me nervous too ^^...

Outras dicas

Not an answer, just a more convenient way to discuss things. You probably know all of the following, but just to make sure…

If you create a Date object in a location, the Date constructor will automatically take into account the local time zone offset. So if I'm at UTC+1000 and create a Date object for 2014-03-27, it will be created for 2014-03-27T00:00:00+1000 (i.e. for my time zone) and the time value of the Date object will be equivalent to 2014-03-26 14:00:00Z, i.e. the equivalent UTC moment, and have a time zone offset of -600 (note that toISOString uses UTC).

var date = new Date(2014, 2, 27);
// toISOString uses UTC
console.log(date.toISOString());  // 2014-03-26T14:00:00.000Z

// Get the time value to pass around
var timeValue = date.getTime();
// or just 
var timeValue = +date;

That moment can be represented in any time zone using UTC methods. For say UTC+0500, you can do:

// Create a Date object
var d = new Date(timeValue);

This Date object will have an offset for the current time zone, but that can be ignored by just using UTC methods:

// Add 5 hours to set the UTC time to the equivalent of UTC+0500
d.setUTCHours(d.getUTCHours() + 5);

// Format for output - 2014-03-26T19:00:00+0500
console.log(d.getUTCFullYear() + '-' + pad(d.getUTCMonth()+1) + '-' + pad(d.getUTCDate()) + 'T' + 
            pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds())
            + '+0500'
);

// Helper for padding
function pad(n){return (n<10?'0':'')+n;}

You probably need a function to format the output for any particular time zone offset using the above. There are also functions available that make a pretty good guess at a users' system's current time zone based on interrogating the result of generating a couple of Date objects so you can get information on daylight saving too.

I hope that helps. :-)

Oh, here's a function for presenting a Date in any time zone:

// Offset is a string in standard ISO offset format
// e.g. '+1000' is UTC+1000, '-0530' is UTC-0530
function toOffsetISOString(d, offset) {

  function pad(n) {return (n<10?  '0' : '') + n;}
  function padd(n){return (n<100? '0' : '') + pad(n);}

  d = new Date(+d);

  var sign = offset < 0? '-':'+';
  var s    = sign == '-'? -1 : 1;
  oset     = Math.abs(offset);

  var hrs = (oset/100 | 0);
  var min = oset % 100;

  d.setUTCHours(d.getUTCHours() + s*hrs, d.getUTCMinutes() + s*min);

  return d.getUTCFullYear() + '-' + pad(d.getUTCMonth()+1) + '-' + pad(d.getUTCDate()) + 'T' + 
                pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds())
                + '.' + padd(d.getUTCMilliseconds()) + offset;
}

var d = new Date();
console.log(d.toISOString() + '\n  ' + toOffsetISOString(d, '+0515'));
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top