Google Apps脚本和RFC 3339问题

时间:2016-03-31 21:29:01

标签: google-apps-script

Google reference documentation中,我找到了一个将RFC3339日期字符串转换为有效Date对象的简短函数。代码非常简单,如下所示:

function parseDate(string) {
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  return new Date(parts.join(' '));
}

问题在于它不起作用。(我很惊讶他们发布的代码不起作用......我错过了什么?)

我在使用JSON进行字符串化和解析日期时也遇到了问题,因为JSON方法返回UTC值(结尾为Z),因此我丢失了时区信息。谷歌的代码也没有处理这个问题(即使它有效)。

下面是我用来测试它的演示代码和我写的解决方案,以获得我想要的东西。不确定它是非常有效还是写得不好,但至少我得到了我想要的结果(我在比利时夏令时设置为GMT + 2的脚本中执行此代码)。 我愿意接受任何改进此代码的建议。(这将成为这个问题的主题)

我在代码中添加了很多日志和注释,以使其尽可能清晰:

function testJSONDate() {
  Logger.log('starting value : "2016/3/31 12:00:00"');
  var jsDate = JSON.stringify(new Date("2016/3/31 12:00:00"));// time is 12:00 I'm in GMT+2
  Logger.log('JSON.stringify value : '+jsDate);
  Logger.log('JSON parse jsDate : '+JSON.parse(jsDate)); // time is 10:00, UTC
  var jsDateWithoutQuotes = jsDate.replace(/"/,'');
  var date = parseDate(jsDateWithoutQuotes); 
  Logger.log('parsed RFC3339 date using Google\'s code : '+date);  // does not return a valid date
  var otherFunction = parseDate2(jsDateWithoutQuotes);
  Logger.log('parsed RFC3339 date using other code : '+otherFunction); // does return a valid date in my TZ
}

function parseDate(string) {
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  return new Date(parts.join(' '));
}
function parseDate2(string) {
  var refStr = new Date().toString();
  var fus = Number(refStr.substr(refStr.indexOf('GMT')+4,2));
  Logger.log('TZ offset = '+fus);
  var parts = string.split('T');
  parts[0] = parts[0].replace(/-/g, '/');
  var t = parts[1].split(':');
  return new Date(new Date(parts[0]).setHours(+t[0]+fus,+t[1],0));
}

记录器结果: enter image description here

首次回答后编辑

在对代码进行少量更改后,我设法让Google的代码段工作,但由于JSON转换JS日期对象的方式,时区丢失的问题仍然存在。

下面的新代码和记录器结果:

function testJSONDate() {
  Logger.log('starting value : 2016/3/31 12:00:00');
  var jsDate = JSON.stringify(new Date("2016/3/31 12:00:00"));// time is 12:00 I'm in GMT+2
  Logger.log('JSON.stringify value : '+jsDate);
  Logger.log('JSON parse jsDate : '+JSON.parse(jsDate)); // time is 10:00, UTC
  var jsDateWithoutQuotesAndMillisecAndZ = jsDate.replace(/"/g,'').split('.')[0];
  Logger.log('jsDateWithoutQuotesAndMillisecAndZ = '+jsDateWithoutQuotesAndMillisecAndZ);
  var date = parseDate(jsDateWithoutQuotesAndMillisecAndZ); 
  Logger.log('parsed RFC3339 date using Google\'s code : '+date);  // does not return a valid date
  var otherFunction = parseDate2(jsDateWithoutQuotesAndMillisecAndZ);
  Logger.log('parsed RFC3339 date using other code : '+otherFunction); // does return a valid date in the right tz
}

enter image description here

1 个答案:

答案 0 :(得分:1)

你已经从上下文中获得了一些辅助功能。它只是作为一个权宜之计设备来获取特定API(Google Calendar API)返回的字符串,以便在Apps脚本中正确解析。它不是任何一种通用日期转换器。项目成员在filing an issue时将它放在一起,并且该线程中的后续消息指出该函数无法处理的另一个细节。

截至目前,Apps Script中的日期解析器正确解析以下格式:

function testdate() {
  Logger.log(new Date("2016/03/31 10:00:00"));       // local time
  Logger.log(new Date("2016/03/31 10:00:00 +2:00")); // with given offset
  Logger.log(new Date("2016-03-31T08:00:00.000Z"));  // in UTC 
}

请注意,UTC时间戳需要毫秒,但其他时间戳不允许。

使用需要解析但不是上述之一的日期时间字符串,取决于其格式。如果您有2016-03-31T10:00:00(显然,这是Google Calendar API返回的内容)并且这意味着在当地时间,那么您需要引用的解析函数所做的事情:用空格替换T,用/替换。如果相同的字符串表示UTC时间,则需要在末尾添加.000Z。等等。