CalendarApp:时区荒谬行为

时间:2014-03-26 22:40:44

标签: javascript google-apps-script google-calendar-api

所以这是我第一次遇到这个错误:

enter image description here

收到此错误的系统是我构建的数据库/日历访问UI。系统需要进行大量测试,我之前从未看到此错误消息。此外,该系统在过去几个月一直运作良好,我的老板只是给我发了一封电子邮件,上面写着错误的截图。

最初似乎问题是所涉及的电子表格和脚本不在同一时区(数据库中事件的时间与日历上的事件不同,所以我认为它是时区)。我把所有东西放在同一时区,似乎工作正常。

然后我再试一次,同样的错误。我做了一些调查,以下内容出现在我的日志中:

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)

当UI显然具有以下值时:

enter image description here

注意:数据库中存在的日期将用户界面DateBox设置为该日期。这意味着在上面的示例中,trainingDate1位于数据库中,因此DateBox.setDate()函数正常工作。但是,trainingDate2之类的日期是我刚刚在UI 中创建的日期,这意味着DateBox小部件没有设置先前的值。我想这就是时间差异的来源。

第二个Date对象实际上是newDate(UI value - 5 hours)肯定会造成问题,因为实际日期会在稍后设置时间后一天结束。

我以前没有遇到过这个问题,老板也没有。这让我相信某个时区存在 ,并且由于某些变化它最近已经发展了...... 然而,我有双重和三重检查时区设置:

  1. 脚本
  2. 在其中访问数据的所有电子表格
  3. 此系统中涉及的所有脚本项目
  4. 使用系统的帐户上的所有日历
  5. 所有时区设置均为 GMT -0500 ,因为它们已持续数月。老实说没有意义 - 我认为时区是问题,但它似乎是随机值发生的......请参阅UI-retreived值的日志中的以下内容:

    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)
    

    UI值如下:

    enter image description here

    editingDate1DateBox值,其值由数据库中的条目设置。然而,更奇怪的是,editingDate2editingDate3相隔一小时(并且两次都错了)。

    那么问题:与DateBox相关的什么类型的时区或其他问题会使值 5或6小时

    请注意,此项目中没有更改时区设置,并且过去3个月内未使用相同的日历和代码;现在这种奇怪的行为正在发生,我无法弄清楚为什么。有什么想法吗?

    PS - 我知道与电子表格时区不同的脚本时区可以often be the source of errors,但我从未在我的DateBox返回预期的小时-5'问题我在发布项目之前进行了两周的广泛测试,并且每个时区的设置与以前完全相同。

    P.P.S。 - 我正在从法国访问该系统,但我已登录到我们工作的托管系统的管理员帐户。我的个人时区差异不应该超越系统时区设置...但是小时数的差异几乎让我相信我只是错过了一些非常明显的东西。

2 个答案:

答案 0 :(得分:1)

不是答案,只是讨论事情的一种更方便的方式。您可能知道以下所有内容,但只是为了确保......

如果在某个位置创建Date对象,Date构造函数将自动考虑本地时区偏移量。因此,如果我在UTC + 1000并为2014-03-27创建一个Date对象,它将为2014-03-27T00:00:00+1000(即我的时区)创建,并且Date对象的时间值将等效于2014-03-26 14:00:00Z,即等效的UTC时刻,时区偏移为-600(注意toISOString使用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;

可以使用UTC方法在任何时区表示该时刻。比如说UTC + 0500,你可以这样做:

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

此Date对象将具有当前时区的偏移量,但只需使用UTC方法即可忽略:

// 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;}

您可能需要一个函数来使用上面的方法格式化任何特定时区偏移的输出。还有一些功能可以根据询问生成几个Date对象的结果,很好地猜测用户系统的当前时区,这样您就可以获得有关夏令时的信息。

我希望有所帮助。 : - )

哦,这是一个在任何时区呈现日期的功能:

// 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'));

答案 1 :(得分:1)

我明白它会让你生气(或紧张),但我猜这个错误没有任何误解,只是对日历时区设置的一个简单误解。

你提到你广泛测试过这段代码,但我很确定你是在没有夏令时转换的时候测试过的。?

您似乎使用&#34; GMT-0500&#34;定义了您的时区。这似乎是一个好主意,但在几天后我们将在夏季时间,这种抵消不再相同,并且由于这种变化,转换日期之后发生的事件现在已经过时了。 / p>

解决方案很简单,使用如下所示的时区字符串,此参数将考虑日期对象中的小时值,并根据夏季/冬季时间自动调整其值。

这应该很容易在您的代码中实现。

"GMT-0500"替换为Session.getScriptTimeZone()

有关此问题的完整说明,请参阅this other recent post,其中我解释了不同的解决方案。

另请注意,其他答案忘记了一个小细节:代码在Google的服务器上执行,而不是在我们的浏览器中执行,因此想法是在创建它的计算机的时区设置中创建日期可能是模棱两可的...它会是我们的电脑还是谷歌的电脑?好问题 !几年前我花了很多时间在这个问题上,前(和关闭)谷歌帮助论坛上充满了关于该主题的帖子,因为当时Session.getScriptTimeZone()并不存在而且它让我太紧张^^ ...